<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
  <meta name="theme-color" content="#222">
  <meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#222">
  <link rel="stylesheet" href="/css/main.css">
  <link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>
  <script id="hexo-configurations">
    var NexT = window.NexT ||
    {};
    var CONFIG = {
      "hostname": "cuiqingcai.com",
      "root": "/",
      "scheme": "Pisces",
      "version": "7.8.0",
      "exturl": false,
      "sidebar":
      {
        "position": "right",
        "width": 360,
        "display": "post",
        "padding": 18,
        "offset": 12,
        "onmobile": false,
        "widgets": [
          {
            "type": "image",
            "name": "阿布云",
            "enable": false,
            "url": "https://www.abuyun.com/http-proxy/introduce.html",
            "src": "https://qiniu.cuiqingcai.com/88au8.jpg",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "天验",
            "enable": true,
            "url": "https://tutorial.lengyue.video/?coupon=12ef4b1a-a3db-11ea-bb37-0242ac130002_cqx_850",
            "src": "https://qiniu.cuiqingcai.com/bco2a.png",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "华为云",
            "enable": false,
            "url": "https://activity.huaweicloud.com/2020_618_promotion/index.html?bpName=5f9f98a29e2c40b780c1793086f29fe2&bindType=1&salesID=wangyubei",
            "src": "https://qiniu.cuiqingcai.com/y42ik.jpg",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "张小鸡",
            "enable": false,
            "url": "http://www.zxiaoji.com/",
            "src": "https://qiniu.cuiqingcai.com/fm72f.png",
            "width": "100%"
      },
          {
            "type": "image",
            "name": "Luminati",
            "src": "https://qiniu.cuiqingcai.com/ikkq9.jpg",
            "url": "https://luminati-china.io/?affiliate=ref_5fbbaaa9647883f5c6f77095",
            "width": "100%",
            "enable": false
      },
          {
            "type": "image",
            "name": "IPIDEA",
            "url": "http://www.ipidea.net/?utm-source=cqc&utm-keyword=?cqc",
            "src": "https://qiniu.cuiqingcai.com/0ywun.png",
            "width": "100%",
            "enable": true
      },
          {
            "type": "tags",
            "name": "标签云",
            "enable": true
      },
          {
            "type": "categories",
            "name": "分类",
            "enable": true
      },
          {
            "type": "friends",
            "name": "友情链接",
            "enable": true
      },
          {
            "type": "hot",
            "name": "猜你喜欢",
            "enable": true
      }]
      },
      "copycode":
      {
        "enable": true,
        "show_result": true,
        "style": "mac"
      },
      "back2top":
      {
        "enable": true,
        "sidebar": false,
        "scrollpercent": true
      },
      "bookmark":
      {
        "enable": false,
        "color": "#222",
        "save": "auto"
      },
      "fancybox": false,
      "mediumzoom": false,
      "lazyload": false,
      "pangu": true,
      "comments":
      {
        "style": "tabs",
        "active": "gitalk",
        "storage": true,
        "lazyload": false,
        "nav": null,
        "activeClass": "gitalk"
      },
      "algolia":
      {
        "hits":
        {
          "per_page": 10
        },
        "labels":
        {
          "input_placeholder": "Search for Posts",
          "hits_empty": "We didn't find any results for the search: ${query}",
          "hits_stats": "${hits} results found in ${time} ms"
        }
      },
      "localsearch":
      {
        "enable": true,
        "trigger": "auto",
        "top_n_per_article": 10,
        "unescape": false,
        "preload": false
      },
      "motion":
      {
        "enable": false,
        "async": false,
        "transition":
        {
          "post_block": "bounceDownIn",
          "post_header": "slideDownIn",
          "post_body": "slideDownIn",
          "coll_header": "slideLeftIn",
          "sidebar": "slideUpIn"
        }
      },
      "path": "search.xml"
    };

  </script>
  <meta name="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  <meta property="og:type" content="website">
  <meta property="og:title" content="静觅">
  <meta property="og:url" content="https://cuiqingcai.com/page/24/index.html">
  <meta property="og:site_name" content="静觅">
  <meta property="og:description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  <meta property="og:locale" content="zh_CN">
  <meta property="article:author" content="崔庆才">
  <meta property="article:tag" content="崔庆才">
  <meta property="article:tag" content="静觅">
  <meta property="article:tag" content="PHP">
  <meta property="article:tag" content="Java">
  <meta property="article:tag" content="Python">
  <meta property="article:tag" content="Spider">
  <meta property="article:tag" content="爬虫">
  <meta property="article:tag" content="Web">
  <meta property="article:tag" content="Kubernetes">
  <meta property="article:tag" content="深度学习">
  <meta property="article:tag" content="机器学习">
  <meta property="article:tag" content="数据分析">
  <meta property="article:tag" content="网络">
  <meta property="article:tag" content="IT">
  <meta property="article:tag" content="技术">
  <meta property="article:tag" content="博客">
  <meta name="twitter:card" content="summary">
  <link rel="canonical" href="https://cuiqingcai.com/page/24/">
  <script id="page-configurations">
    // https://hexo.io/docs/variables.html
    CONFIG.page = {
      sidebar: "",
      isHome: true,
      isPost: false,
      lang: 'zh-CN'
    };

  </script>
  <title>静觅丨崔庆才的个人站点</title>
  <meta name="google-site-verification" content="p_bIcnvirkFzG2dYKuNDivKD8-STet5W7D-01woA2fc" />
  <noscript>
    <style>
      .use-motion .brand,
      .use-motion .menu-item,
      .sidebar-inner,
      .use-motion .post-block,
      .use-motion .pagination,
      .use-motion .comments,
      .use-motion .post-header,
      .use-motion .post-body,
      .use-motion .collection-header
      {
        opacity: initial;
      }

      .use-motion .site-title,
      .use-motion .site-subtitle
      {
        opacity: initial;
        top: initial;
      }

      .use-motion .logo-line-before i
      {
        left: initial;
      }

      .use-motion .logo-line-after i
      {
        right: initial;
      }

    </style>
  </noscript>
  <link rel="alternate" href="/atom.xml" title="静觅" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container">
    <div class="headband"></div>
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner">
        <div class="site-brand-container">
          <div class="site-nav-toggle">
            <div class="toggle" aria-label="切换导航栏">
              <span class="toggle-line toggle-line-first"></span>
              <span class="toggle-line toggle-line-middle"></span>
              <span class="toggle-line toggle-line-last"></span>
            </div>
          </div>
          <div class="site-meta">
            <a href="/" class="brand" rel="start">
              <span class="logo-line-before"><i></i></span>
              <h1 class="site-title">静觅 <span class="site-subtitle"> 崔庆才的个人站点 </span>
              </h1>
              <span class="logo-line-after"><i></i></span>
            </a>
          </div>
          <div class="site-nav-right">
            <div class="toggle popup-trigger">
              <i class="fa fa-search fa-fw fa-lg"></i>
            </div>
          </div>
        </div>
        <nav class="site-nav">
          <ul id="menu" class="main-menu menu">
            <li class="menu-item menu-item-home">
              <a href="/" rel="section">首页</a>
            </li>
            <li class="menu-item menu-item-archives">
              <a href="/archives/" rel="section">文章列表</a>
            </li>
            <li class="menu-item menu-item-tags">
              <a href="/tags/" rel="section">文章标签</a>
            </li>
            <li class="menu-item menu-item-categories">
              <a href="/categories/" rel="section">文章分类</a>
            </li>
            <li class="menu-item menu-item-about">
              <a href="/about/" rel="section">关于博主</a>
            </li>
            <li class="menu-item menu-item-message">
              <a href="/message/" rel="section">给我留言</a>
            </li>
            <li class="menu-item menu-item-search">
              <a role="button" class="popup-trigger">搜索 </a>
            </li>
          </ul>
        </nav>
        <div class="search-pop-overlay">
          <div class="popup search-popup">
            <div class="search-header">
              <span class="search-icon">
                <i class="fa fa-search"></i>
              </span>
              <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off" placeholder="搜索..." spellcheck="false" type="search" class="search-input">
              </div>
              <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
              </span>
            </div>
            <div id="search-result">
              <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
              </div>
            </div>
          </div>
        </div>
      </div>
    </header>
    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
      <span>0%</span>
    </div>
    <div class="reading-progress-bar"></div>
    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div class="content index posts-expand">
            <div class="carousel">
              <div id="wowslider-container">
                <div class="ws_images">
                  <ul>
                    <li><a target="_blank" href="https://cuiqingcai.com/5052.html"><img title="Python3网络爬虫开发实战教程" src="https://qiniu.cuiqingcai.com/ipy96.jpg" /></a></li>
                    <li><a target="_blank" href="https://t.lagou.com/fRCBRsRCSN6FA"><img title="52讲轻松搞定网络爬虫" src="https://qiniu.cuiqingcai.com/fqq5e.png" /></a></li>
                    <li><a target="_blank" href="https://brightdata.grsm.io/cuiqingcai"><img title="亮网络解锁器" src="https://qiniu.cuiqingcai.com/6qnb7.png" /></a></li>
                    <li><a target="_blank" href="https://cuiqingcai.com/4320.html"><img title="Python3网络爬虫开发视频教程" src="https://qiniu.cuiqingcai.com/bjrny.jpg" /></a></li>
                    <li><a target="_blank" href="https://cuiqingcai.com/5094.html"><img title="爬虫代理哪家强？十大付费代理详细对比评测出炉！" src="https://qiniu.cuiqingcai.com/nifs6.jpg" /></a></li>
                  </ul>
                </div>
                <div class="ws_thumbs">
                  <div>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/ipy96.jpg" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/fqq5e.png" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/6qnb7.png" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/bjrny.jpg" /></a>
                    <a target="_blank" href="#"><img src="https://qiniu.cuiqingcai.com/nifs6.jpg" /></a>
                  </div>
                </div>
                <div class="ws_shadow"></div>
              </div>
            </div>
            <link rel="stylesheet" href="/lib/wowslide/slide.css">
            <script src="/lib/wowslide/jquery.min.js"></script>
            <script src="/lib/wowslide/slider.js"></script>
            <script>
              jQuery("#wowslider-container").wowSlider(
              {
                effect: "cube",
                prev: "",
                next: "",
                duration: 20 * 100,
                delay: 20 * 100,
                width: 716,
                height: 297,
                autoPlay: true,
                playPause: true,
                stopOnHover: false,
                loop: false,
                bullets: 0,
                caption: true,
                captionEffect: "slide",
                controls: true,
                onBeforeStep: 0,
                images: 0
              });

            </script>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2577.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> Python <i class="label-arrow"></i>
                  </a>
                  <a href="/2577.html" class="post-title-link" itemprop="url">Python爬虫利器四之PhantomJS的用法</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2>
                  <p>大家有没有发现之前我们写的爬虫都有一个共性，就是只能爬取单纯的html代码，如果页面是JS渲染的该怎么办呢？如果我们单纯去分析一个个后台的请求，手动去摸索JS渲染的到的一些结果，那简直没天理了。所以，我们需要有一些好用的工具来帮助我们像浏览器一样渲染JS处理的页面。 其中有一个比较常用的工具，那就是 <a href="http://phantomjs.org/" target="_blank" rel="noopener">PhantomJS</a></p>
                  <blockquote>
                    <p>Full web stack No browser required</p>
                    <p>PhantomJS is a headless WebKit scriptable with a JavaScript API. It has <strong>fast</strong> and<strong>native</strong> support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.</p>
                  </blockquote>
                  <p>PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎。它原生支持多种web 标准：DOM 操作，CSS选择器，JSON，Canvas 以及SVG。 好，接下来我们就一起来了解一下这个神奇好用的库的用法吧。</p>
                  <h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2>
                  <p>PhantomJS安装方法有两种，一种是下载源码之后自己来编译，另一种是直接下载编译好的二进制文件。然而自己编译需要的时间太长，而且需要挺多的磁盘空间。官方推荐直接下载二进制文件然后安装。 大家可以依照自己的开发平台选择不同的包进行下载 <a href="http://phantomjs.org/download.html" target="_blank" rel="noopener">下载地址</a> 当然如果你不嫌麻烦，可以选择 <a href="http://phantomjs.org/build.html" target="_blank" rel="noopener">下载源码</a> 然后自己编译。 目前（2016/3/21）最新发行版本是 v2.1， 安装完成之后命令行输入</p>
                  <figure class="highlight ebnf">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attribute">phantomjs -v</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果正常显示版本号，那么证明安装成功了。如果提示错误，那么请重新安装。 本文介绍大部分内容来自于官方文档，博主对其进行了整理，学习更多请参考 <a href="http://phantomjs.org/quick-start.html" target="_blank" rel="noopener">官方文档</a></p>
                  <h2 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h2>
                  <h3 id="第一个程序"><a href="#第一个程序" class="headerlink" title="第一个程序"></a>第一个程序</h3>
                  <p>第一个程序当然是Hello World，新建一个 js 文件。命名为 helloworld.js</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">console.log(<span class="string">'Hello, world!'</span>);</span><br><span class="line">phantom.<span class="keyword">exit</span>();</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>命令行输入</p>
                  <figure class="highlight css">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="selector-tag">phantomjs</span> <span class="selector-tag">helloworld</span><span class="selector-class">.js</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>程序输出了 Hello，world！程序第二句话终止了 phantom 的执行。 <strong>注意：<code>phantom.exit();</code>这句话非常重要，否则程序将永远不会终止。</strong></p>
                  <h3 id="页面加载"><a href="#页面加载" class="headerlink" title="页面加载"></a>页面加载</h3>
                  <p>可以利用 phantom 来实现页面的加载，下面的例子实现了页面的加载并将页面保存为一张图片。</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var page = require(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.open(<span class="string">'http://cuiqingcai.com'</span>, <span class="keyword">function</span> (status) &#123;</span><br><span class="line">    console.log(<span class="string">"Status: "</span> + status);</span><br><span class="line">    <span class="keyword">if</span> (status === <span class="string">"success"</span>) &#123;</span><br><span class="line">        page.render(<span class="string">'example.png'</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    phantom.<span class="keyword">exit</span>();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>首先创建了一个webpage对象，然后加载本站点主页，判断响应状态，如果成功，那么保存截图为 example.png 以上代码命名为 pageload.js，命令行</p>
                  <figure class="highlight css">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="selector-tag">phantomjs</span> <span class="selector-tag">pageload</span><span class="selector-class">.js</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>发现执行成功，然后目录下多了一张图片，example.png <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/03/example-e1458570294781.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/03/example-e1458570294781.png" alt="example"></a> 因为这个 render 方法，phantom 经常会用到网页截图的功能。</p>
                  <h3 id="测试页面加载速度"><a href="#测试页面加载速度" class="headerlink" title="测试页面加载速度"></a>测试页面加载速度</h3>
                  <p>下面这个例子计算了一个页面的加载速度，同时还用到了命令行传参的特性。新建文件保存为 loadspeed.js</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var<span class="built_in"> page </span>= require(<span class="string">'webpage'</span>).create(),</span><br><span class="line"> <span class="built_in"> system </span>= require(<span class="string">'system'</span>),</span><br><span class="line">  t, address;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (system.args.length === 1) &#123;</span><br><span class="line">  console.log(<span class="string">'Usage: loadspeed.js &lt;some URL&gt;'</span>);</span><br><span class="line">  phantom.exit();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">t = Date.now();</span><br><span class="line">address = system.args[1];</span><br><span class="line">page.open(address, function(status) &#123;</span><br><span class="line">  <span class="keyword">if</span> (status !== <span class="string">'success'</span>) &#123;</span><br><span class="line">    console.log(<span class="string">'FAIL to load the address'</span>);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    t = Date.now() - t;</span><br><span class="line">    console.log(<span class="string">'Loading '</span> + system.args[1]);</span><br><span class="line">    console.log(<span class="string">'Loading time '</span> + t + <span class="string">' msec'</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  phantom.exit();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>程序判断了参数的多少，如果参数不够，那么终止运行。然后记录了打开页面的时间，请求页面之后，再纪录当前时间，二者之差就是页面加载速度。</p>
                  <figure class="highlight groovy">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">phantomjs loadspeed.js <span class="string">http:</span><span class="comment">//cuiqingcai.com</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight angelscript">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">Loading http:<span class="comment">//cuiqingcai.com</span></span><br><span class="line">Loading time <span class="number">11678</span> msec</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这个时间包括JS渲染的时间，当然和网速也有关。</p>
                  <h3 id="代码评估"><a href="#代码评估" class="headerlink" title="代码评估"></a>代码评估</h3>
                  <blockquote>
                    <p>To evaluate JavaScript code in the context of the web page, use <code>evaluate()</code> function. The execution is “sandboxed”, there is no way for the code to access any JavaScript objects and variables outside its own page context. An object can be returned from <code>evaluate()</code>, however it is limited to simple objects and can’t contain functions or closures.</p>
                  </blockquote>
                  <p>利用 evaluate 方法我们可以获取网页的源代码。这个执行是“沙盒式”的，它不会去执行网页外的 JavaScript 代码。evalute 方法可以返回一个对象，然而返回值仅限于对象，不能包含函数（或闭包）</p>
                  <figure class="highlight qml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">var</span> <span class="built_in">url</span> = <span class="string">'http://www.baidu.com'</span>;</span><br><span class="line"><span class="keyword">var</span> page = <span class="built_in">require</span>(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.open(<span class="built_in">url</span>, <span class="function"><span class="keyword">function</span>(<span class="params">status</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> title = page.evaluate(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">document</span>.title;</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'Page title is '</span> + title);</span><br><span class="line">  phantom.exit();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以上代码获取了百度的网站标题。</p>
                  <figure class="highlight maxima">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">Page <span class="built_in">title</span> <span class="built_in">is</span> 百度一下，你就知道</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>任何来自于网页并且包括来自 evaluate() 内部代码的控制台信息，默认不会显示。 需要重写这个行为，使用 onConsoleMessage 回调函数，示例可以改写成</p>
                  <figure class="highlight qml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">var</span> <span class="built_in">url</span> = <span class="string">'http://www.baidu.com'</span>;</span><br><span class="line"><span class="keyword">var</span> page = <span class="built_in">require</span>(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.onConsoleMessage = <span class="function"><span class="keyword">function</span> (<span class="params">msg</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(msg);</span><br><span class="line">&#125;;</span><br><span class="line">page.open(<span class="built_in">url</span>, <span class="function"><span class="keyword">function</span> (<span class="params">status</span>) </span>&#123;</span><br><span class="line">    page.evaluate(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">document</span>.title);</span><br><span class="line">    &#125;);</span><br><span class="line">    phantom.exit();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这样的话，如果你用浏览器打开百度首页，打开调试工具的console，可以看到控制台输出信息。 重写了 onConsoleMessage 方法之后，可以发现控制台输出的结果和我们需要输出的标题都打印出来了。</p>
                  <figure class="highlight groovy">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">一张网页，要经历怎样的过程，才能抵达用户面前？</span><br><span class="line">一位新人，要经历怎样的成长，才能站在技术之巅？</span><br><span class="line">探寻这里的秘密；</span><br><span class="line">体验这里的挑战；</span><br><span class="line">成为这里的主人；</span><br><span class="line">加入百度，加入网页搜索，你，可以影响世界。</span><br><span class="line"></span><br><span class="line">请将简历发送至 %c ps_recruiter<span class="meta">@baidu</span>.com（ 邮件标题请以“姓名-应聘XX职位-来自console”命名） <span class="string">color:</span>red</span><br><span class="line">职位介绍：<span class="string">http:</span><span class="comment">//dwz.cn/hr2013</span></span><br><span class="line">百度一下，你就知道</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>啊，我没有在为百度打广告！</p>
                  <h2 id="屏幕捕获"><a href="#屏幕捕获" class="headerlink" title="屏幕捕获"></a>屏幕捕获</h2>
                  <blockquote>
                    <p>Since PhantomJS is using WebKit, a real layout and rendering engine, it can capture a web page as a screenshot. Because PhantomJS can render anything on the web page, it can be used to convert contents not only in HTML and CSS, but also SVG and Canvas.</p>
                  </blockquote>
                  <p>因为 PhantomJS 使用了 WebKit内核，是一个真正的布局和渲染引擎，它可以像屏幕截图一样捕获一个web界面。因为它可以渲染网页中的人和元素，所以它不仅用到HTML，CSS的内容转化，还用在SVG，Canvas。可见其功能是相当强大的。 下面的例子就捕获了github网页的截图。上文有类似内容，不再演示。</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var page = require(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.open(<span class="string">'http://github.com/'</span>, <span class="keyword">function</span>() &#123;</span><br><span class="line">  page.render(<span class="string">'github.png'</span>);</span><br><span class="line">  phantom.<span class="keyword">exit</span>();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>除了 png 格式的转换，PhantomJS还支持 jpg，gif，pdf等格式。 <a href="https://github.com/ariya/phantomjs/blob/master/examples/rasterize.js" target="_blank" rel="noopener">测试样例</a> 其中最重要的方法便是 viewportSize 和 clipRect 属性。 viewportSize 是视区的大小，你可以理解为你打开了一个浏览器，然后把浏览器窗口拖到了多大。 clipRect 是裁切矩形的大小，需要四个参数，前两个是基准点，后两个参数是宽高。 通过下面的小例子感受一下。</p>
                  <figure class="highlight groovy">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var page = require(<span class="string">'webpage'</span>).create();</span><br><span class="line"><span class="comment">//viewportSize being the actual size of the headless browser</span></span><br><span class="line">page.viewportSize = &#123; <span class="string">width:</span> <span class="number">1024</span>, <span class="string">height:</span> <span class="number">768</span> &#125;;</span><br><span class="line"><span class="comment">//the clipRect is the portion of the page you are taking a screenshot of</span></span><br><span class="line">page.clipRect = &#123; <span class="string">top:</span> <span class="number">0</span>, <span class="string">left:</span> <span class="number">0</span>, <span class="string">width:</span> <span class="number">1024</span>, <span class="string">height:</span> <span class="number">768</span> &#125;;</span><br><span class="line"><span class="comment">//the rest of the code is the same as the previous example</span></span><br><span class="line">page.open(<span class="string">'http://cuiqingcai.com/'</span>, function() &#123;</span><br><span class="line">  page.render(<span class="string">'germy.png'</span>);</span><br><span class="line">  phantom.exit();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/03/germy.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/03/germy.png" alt="germy"></a> 就相当于把浏览器窗口拖到了 1024x768 大小，然后从左上角裁切出了 1024x768 的页面。</p>
                  <h2 id="网络监听"><a href="#网络监听" class="headerlink" title="网络监听"></a>网络监听</h2>
                  <blockquote>
                    <p>Because PhantomJS permits the inspection of network traffic, it is suitable to build various analysis on the network behavior and performance.</p>
                  </blockquote>
                  <p>因为 PhantomJS 有网络通信的检查功能，它也很适合用来做网络行为的分析。</p>
                  <blockquote>
                    <p>When a page requests a resource from a remote server, both the request and the response can be tracked via onResourceRequested and onResourceReceived callback.</p>
                  </blockquote>
                  <p>当接受到请求时，可以通过改写onResourceRequested和onResourceReceived回调函数来实现接收到资源请求和资源接受完毕的监听。例如</p>
                  <figure class="highlight qml">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">var</span> <span class="built_in">url</span> = <span class="string">'http://www.cuiqingcai.com'</span>;</span><br><span class="line"><span class="keyword">var</span> page = <span class="built_in">require</span>(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.onResourceRequested = <span class="function"><span class="keyword">function</span>(<span class="params">request</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'Request '</span> + <span class="built_in">JSON</span>.stringify(request, <span class="literal">undefined</span>, <span class="number">4</span>));</span><br><span class="line">&#125;;</span><br><span class="line">page.onResourceReceived = <span class="function"><span class="keyword">function</span>(<span class="params">response</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'Receive '</span> + <span class="built_in">JSON</span>.stringify(response, <span class="literal">undefined</span>, <span class="number">4</span>));</span><br><span class="line">&#125;;</span><br><span class="line">page.open(<span class="built_in">url</span>);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果会打印出所有资源的请求和接收状态，以JSON格式输出。</p>
                  <h2 id="页面自动化处理"><a href="#页面自动化处理" class="headerlink" title="页面自动化处理"></a>页面自动化处理</h2>
                  <blockquote>
                    <p>Because PhantomJS can load and manipulate a web page, it is perfect to carry out various page automations.</p>
                  </blockquote>
                  <p>因为 PhantomJS 可以加载和操作一个web页面，所以用来自动化处理也是非常适合的。</p>
                  <h3 id="DOM操作"><a href="#DOM操作" class="headerlink" title="DOM操作"></a>DOM操作</h3>
                  <blockquote>
                    <p>Since the script is executed as if it is running on a web browser, standard DOM scripting and CSS selectors work just fine.</p>
                  </blockquote>
                  <p>脚本都是像在浏览器中运行的，所以标准的 JavaScript 的 DOM 操作和 CSS 选择器也是生效的。 例如下面的例子就修改了 User-Agent，然后还返回了页面中某元素的内容。</p>
                  <figure class="highlight lua">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var page = <span class="built_in">require</span>(<span class="string">'webpage'</span>).<span class="built_in">create</span>();</span><br><span class="line">console.<span class="built_in">log</span>(<span class="string">'The default user agent is '</span> + page.settings.userAgent);</span><br><span class="line">page.settings.userAgent = <span class="string">'SpecialAgent'</span>;</span><br><span class="line">page.<span class="built_in">open</span>(<span class="string">'http://www.httpuseragent.org'</span>, <span class="function"><span class="keyword">function</span><span class="params">(status)</span></span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">status</span> !== <span class="string">'success'</span>) &#123;</span><br><span class="line">    console.<span class="built_in">log</span>(<span class="string">'Unable to access network'</span>);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    var ua = page.evaluate(<span class="function"><span class="keyword">function</span><span class="params">()</span></span> &#123;</span><br><span class="line">      <span class="keyword">return</span> document.getElementById(<span class="string">'myagent'</span>).textContent;</span><br><span class="line">    &#125;);</span><br><span class="line">    console.<span class="built_in">log</span>(ua);</span><br><span class="line">  &#125;</span><br><span class="line">  phantom.<span class="built_in">exit</span>();</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">The<span class="built_in"> default user </span>agent is Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.0 Safari/538.1</span><br><span class="line">Your Http<span class="built_in"> User </span>Agent string is: SpecialAgent</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>首先打印出了默认的 User-Agent，然后通过修改它，请求验证 User-Agent 的一个站点，通过选择器得到了修改后的 User-Agent。</p>
                  <h3 id="使用附加库"><a href="#使用附加库" class="headerlink" title="使用附加库"></a>使用附加库</h3>
                  <p>在1.6版本之后允许添加外部的JS库，比如下面的例子添加了jQuery，然后执行了jQuery代码。</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">var page = require(<span class="string">'webpage'</span>).create();</span><br><span class="line">page.open(<span class="string">'http://www.sample.com'</span>, <span class="keyword">function</span>() &#123;</span><br><span class="line">  page.includeJs(<span class="string">"http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"</span>, <span class="keyword">function</span>() &#123;</span><br><span class="line">    page.evaluate(<span class="keyword">function</span>() &#123;</span><br><span class="line">      $(<span class="string">"button"</span>).click();</span><br><span class="line">    &#125;);</span><br><span class="line">    phantom.<span class="keyword">exit</span>()</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>引用了 jQuery 之后，我们便可以在下面写一些 jQuery 代码了。</p>
                  <h2 id="Webpage对象"><a href="#Webpage对象" class="headerlink" title="Webpage对象"></a>Webpage对象</h2>
                  <p>在前面我们介绍了 webpage 对象的几个方法和属性，其实它本身还有其它很多的属性。具体的内容可以参考 <a href="http://phantomjs.org/page-automation.html" target="_blank" rel="noopener">Webpage</a> <a href="https://github.com/ariya/phantomjs/blob/master/examples/page_events.js" target="_blank" rel="noopener">Webpage用例</a> 里面介绍了 webpage的所有属性，方法，回调。</p>
                  <h2 id="命令行"><a href="#命令行" class="headerlink" title="命令行"></a>命令行</h2>
                  <p>Command-line Options PhantomJS提供的命令行选项有：</p>
                  <blockquote>
                    <p>--help or -h lists all possible command-line options. Halts immediately, will not run a script passed as argument. ［帮助列表］ —version or -v prints out the version of PhantomJS. Halts immediately, will not run a script passed as argument. ［查看版本］ —cookies-file=/path/to/cookies.txt specifies the file name to store the persistent Cookies. ［指定存放cookies的路径］ —disk-cache=[true|false] enables disk cache (at desktop services cache storage location, default is false). Also accepted: [yes|no]. ［硬盘缓存开关，默认为关］ —ignore-ssl-errors=[true|false] ignores SSL errors, such as expired or self-signed certificate errors (default is false). Also accepted: [yes|no]. ［忽略ssl错误，默认不忽略］ —load-images=[true|false] load all inlined images (default is true). Also accepted: [yes|no]. ［加载图片，默认为加载］ —local-storage-path=/some/path path to save LocalStorage content and WebSQL content. ［本地存储路径，如本地文件和SQL文件等］ —local-storage-quota=number maximum size to allow for data. ［本地文件最大大小］ —local-to-remote-url-access=[true|false] allows local content to access remote URL (default is false). Also accepted: [yes|no]. ［是否允许远程加载文件，默认不允许］ —max-disk-cache-size=size limits the size of disk cache (in KB). ［最大缓存空间］ —output-encoding=encoding sets the encoding used for terminal output (default is utf8). ［默认输出编码，默认utf8］ —remote-debugger-port starts the script in a debug harness and listens on the specified port ［远程调试端口］ —remote-debugger-autorun runs the script in the debugger immediately: ‘yes’ or ‘no’ (default) ［在调试环境下是否立即执行脚本，默认否］ —proxy=address:port specifies the proxy server to use (e.g. —proxy=192.168.1.42:8080). ［代理］ —proxy-type=[http|socks5|none] specifies the type of the proxy server (default is http). ［代理类型，默认http］ —proxy-auth specifies the authentication information for the proxy, e.g. —proxy-auth=username:password). ［代理认证］ —script-encoding=encoding sets the encoding used for the starting script (default is utf8). ［脚本编码，默认utf8］ —ssl-protocol=[sslv3|sslv2|tlsv1|any’] sets the SSL protocol for secure connections (default is SSLv3). ［SSL协议，默认SSLv3］ —ssl-certificates-path=<val> Sets the location for custom CA certificates (if none set, uses system default). ［SSL证书路径，默认系统默认路径］ —web-security=[true|false] enables web security and forbids cross-domain XHR (default is true). Also accepted: [yes|no]. ［是否开启安全保护和禁止异站Ajax，默认开启保护］ —webdriver starts in ‘Remote WebDriver mode’ (embedded GhostDriver): ‘[[:]]’ (default ‘127.0.0.1:8910’) ［以远程WebDriver模式启动］ —webdriver-selenium-grid-hub URL to the Selenium Grid HUB: ‘URLTOHUB’ (default ‘none’) (NOTE: works only together with ‘—webdriver’) ［Selenium接口］ —config=/path/to/config.json can utilize a JavaScript Object Notation (JSON) configuration file instead of passing in multiple command-line optionss ［所有的命令行配置从config.json中读取］</p>
                  </blockquote>
                  <p>注：JSON文件配置格式</p>
                  <figure class="highlight arcade">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="comment">/* Same as: --ignore-ssl-errors=true */</span></span><br><span class="line">  <span class="string">"ignoreSslErrors"</span>: <span class="literal">true</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Same as: --max-disk-cache-size=1000 */</span></span><br><span class="line">  <span class="string">"maxDiskCacheSize"</span>: <span class="number">1000</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Same as: --output-encoding=utf8 */</span></span><br><span class="line">  <span class="string">"outputEncoding"</span>: <span class="string">"utf8"</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">/* etc. */</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">There are some keys that <span class="keyword">do</span> not translate directly:</span><br><span class="line"></span><br><span class="line"> * --disk-<span class="function"><span class="params">cache</span> =&gt;</span> diskCacheEnabled</span><br><span class="line"> * --load-<span class="function"><span class="params">images</span> =&gt;</span> autoLoadImages</span><br><span class="line"> * --local-storage-<span class="function"><span class="params">path</span> =&gt;</span> offlineStoragePath</span><br><span class="line"> * --local-storage-<span class="function"><span class="params">quota</span> =&gt;</span> offlineStorageDefaultQuota</span><br><span class="line"> * --local-to-remote-url-<span class="function"><span class="params">access</span> =&gt;</span> localToRemoteUrlAccessEnabled</span><br><span class="line"> * --web-<span class="function"><span class="params">security</span> =&gt;</span> webSecurityEnabled</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以上是命令行的基本配置</p>
                  <h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2>
                  <p>在此提供官方文档实例，多对照实例练习，使用起来会更得心应手。 <a href="http://phantomjs.org/examples/index.html" target="_blank" rel="noopener">官方实例</a></p>
                  <h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2>
                  <p>以上是博主对 PhantomJS 官方文档的基本总结和翻译，如有差错，希望大家可以指正。另外可能有的小伙伴觉得这个工具和 Python 有什么关系？不要急，后面会有 Python 和 PhantomJS 的综合使用的。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2016-03-22 00:56:03" itemprop="dateCreated datePublished" datetime="2016-03-22T00:56:03+08:00">2016-03-22</time>
                </span>
                <span id="/2577.html" class="post-meta-item leancloud_visitors" data-flag-title="Python爬虫利器四之PhantomJS的用法" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>9.9k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>9 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2556.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> Python <i class="label-arrow"></i>
                  </a>
                  <a href="/2556.html" class="post-title-link" itemprop="url">Python爬虫利器一之Requests库的用法</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2>
                  <p>之前我们用了 urllib 库，这个作为入门的工具还是不错的，对了解一些爬虫的基本理念，掌握爬虫爬取的流程有所帮助。入门之后，我们就需要学习一些更加高级的内容和工具来方便我们的爬取。那么这一节来简单介绍一下 requests 库的基本用法。 <strong>注：Python 版本依然基于 2.7</strong></p>
                  <h2 id="官方文档"><a href="#官方文档" class="headerlink" title="官方文档"></a>官方文档</h2>
                  <p>以下内容大多来自于官方文档，本文进行了一些修改和总结。要了解更多可以参考 <a href="http://docs.python-requests.org/en/master/" target="_blank" rel="noopener">官方文档</a></p>
                  <h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2>
                  <p>利用 pip 安装</p>
                  <figure class="highlight cmake">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">$ pip <span class="keyword">install</span> requests</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>或者利用 easy_install</p>
                  <figure class="highlight elixir">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="variable">$ </span>easy_install requests</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>通过以上两种方法均可以完成安装。</p>
                  <h2 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h2>
                  <p>首先我们引入一个小例子来感受一下</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">'http://cuiqingcai.com'</span>)</span><br><span class="line"><span class="builtin-name">print</span> type(r)</span><br><span class="line"><span class="builtin-name">print</span> r.status_code</span><br><span class="line"><span class="builtin-name">print</span> r.encoding</span><br><span class="line"><span class="comment">#print r.text</span></span><br><span class="line"><span class="builtin-name">print</span> r.cookies</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以上代码我们请求了本站点的网址，然后打印出了返回结果的类型，状态码，编码方式，Cookies等内容。 运行结果如下</p>
                  <figure class="highlight apache">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="section">&lt;class 'requests.models.Response'&gt;</span></span><br><span class="line"><span class="attribute">200</span></span><br><span class="line"><span class="attribute">UTF</span>-8</span><br><span class="line"><span class="section">&lt;RequestsCookieJar[]&gt;</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>怎样，是不是很方便。别急，更方便的在后面呢。</p>
                  <h2 id="基本请求"><a href="#基本请求" class="headerlink" title="基本请求"></a>基本请求</h2>
                  <p>requests库提供了http所有的基本请求方式。例如</p>
                  <figure class="highlight ini">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attr">r</span> = requests.post(<span class="string">"http://httpbin.org/post"</span>)</span><br><span class="line"><span class="attr">r</span> = requests.put(<span class="string">"http://httpbin.org/put"</span>)</span><br><span class="line"><span class="attr">r</span> = requests.delete(<span class="string">"http://httpbin.org/delete"</span>)</span><br><span class="line"><span class="attr">r</span> = requests.head(<span class="string">"http://httpbin.org/get"</span>)</span><br><span class="line"><span class="attr">r</span> = requests.options(<span class="string">"http://httpbin.org/get"</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>嗯，一句话搞定。</p>
                  <h2 id="基本GET请求"><a href="#基本GET请求" class="headerlink" title="基本GET请求"></a>基本GET请求</h2>
                  <p>最基本的GET请求可以直接用get方法</p>
                  <figure class="highlight ini">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attr">r</span> = requests.get(<span class="string">"http://httpbin.org/get"</span>)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果想要加参数，可以利用 params 参数</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">payload = &#123;<span class="string">'key1'</span>: <span class="string">'value1'</span>, <span class="string">'key2'</span>: <span class="string">'value2'</span>&#125;</span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">"http://httpbin.org/get"</span>, <span class="attribute">params</span>=payload)</span><br><span class="line"><span class="builtin-name">print</span> r.url</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight avrasm">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="symbol">http:</span>//httpbin<span class="meta">.org</span>/get?key2=value2&amp;key1=value1</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果想请求JSON文件，可以利用 json() 方法解析 例如自己写一个JSON文件命名为a.json，内容如下</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="string">"foo"</span>, <span class="string">"bar"</span>, &#123;</span><br><span class="line">  <span class="attr">"foo"</span>: <span class="string">"bar"</span></span><br><span class="line">&#125;]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>利用如下程序请求并解析</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">"a.json"</span>)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br><span class="line"><span class="builtin-name">print</span> r.json()</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果如下，其中一个是直接输出内容，另外一个方法是利用 json() 方法解析，感受下它们的不同</p>
                  <figure class="highlight awk">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">[<span class="string">"foo"</span>, <span class="string">"bar"</span>, &#123;</span><br><span class="line"> <span class="string">"foo"</span>: <span class="string">"bar"</span></span><br><span class="line"> &#125;]</span><br><span class="line"> [<span class="string">u'foo'</span>, <span class="string">u'bar'</span>, &#123;<span class="string">u'foo'</span>: <span class="string">u'bar'</span>&#125;]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果想获取来自服务器的原始套接字响应，可以取得 r.raw 。 不过需要在初始请求中设置 stream=True 。</p>
                  <figure class="highlight llvm">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">r = requests.get('https://github.com/timeline.json', stream=True)</span><br><span class="line">r.raw</span><br><span class="line">&lt;requests.packages.urllib<span class="number">3</span>.response.HTTPResponse object at <span class="number">0x101194810</span>&gt;</span><br><span class="line">r.raw.read(<span class="number">10</span>)</span><br><span class="line">'\<span class="keyword">x</span><span class="number">1</span>f\<span class="keyword">x</span><span class="number">8</span>b\<span class="keyword">x</span><span class="number">08</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">00</span>\<span class="keyword">x</span><span class="number">03</span>'</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这样就获取了网页原始套接字内容。 如果想添加 headers，可以传 headers 参数</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">payload = &#123;<span class="string">'key1'</span>: <span class="string">'value1'</span>, <span class="string">'key2'</span>: <span class="string">'value2'</span>&#125;</span><br><span class="line">headers = &#123;<span class="string">'content-type'</span>: <span class="string">'application/json'</span>&#125;</span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">"http://httpbin.org/get"</span>, <span class="attribute">params</span>=payload, <span class="attribute">headers</span>=headers)</span><br><span class="line"><span class="builtin-name">print</span> r.url</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>通过headers参数可以增加请求头中的headers信息</p>
                  <h2 id="基本POST请求"><a href="#基本POST请求" class="headerlink" title="基本POST请求"></a>基本POST请求</h2>
                  <p>对于 POST 请求来说，我们一般需要为它增加一些参数。那么最基本的传参方法可以利用 data 这个参数。</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">payload = &#123;<span class="string">'key1'</span>: <span class="string">'value1'</span>, <span class="string">'key2'</span>: <span class="string">'value2'</span>&#125;</span><br><span class="line">r = requests.post(<span class="string">"http://httpbin.org/post"</span>, <span class="attribute">data</span>=payload)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"args"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"data"</span>: <span class="string">""</span>, </span><br><span class="line">  <span class="attr">"files"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"form"</span>: &#123;</span><br><span class="line">    <span class="attr">"key1"</span>: <span class="string">"value1"</span>, </span><br><span class="line">    <span class="attr">"key2"</span>: <span class="string">"value2"</span></span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Content-Length"</span>: <span class="string">"23"</span>, </span><br><span class="line">    <span class="attr">"Content-Type"</span>: <span class="string">"application/x-www-form-urlencoded"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span></span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">"json"</span>: <span class="literal">null</span>, </span><br><span class="line">  <span class="attr">"url"</span>: <span class="string">"http://httpbin.org/post"</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>可以看到参数传成功了，然后服务器返回了我们传的数据。 有时候我们需要传送的信息不是表单形式的，需要我们传JSON格式的数据过去，所以我们可以用 json.dumps() 方法把表单数据序列化。</p>
                  <figure class="highlight haskell">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="title">url</span> = 'http://httpbin.org/post'</span><br><span class="line"><span class="title">payload</span> = &#123;'some': '<span class="class"><span class="keyword">data</span>'&#125;</span></span><br><span class="line"><span class="title">r</span> = requests.post(url, <span class="class"><span class="keyword">data</span>=json.dumps(<span class="title">payload</span>))</span></span><br><span class="line"><span class="title">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"args"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"data"</span>: <span class="string">"&#123;\"some\": \"data\"&#125;"</span>, </span><br><span class="line">  <span class="attr">"files"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"form"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Content-Length"</span>: <span class="string">"16"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span></span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">"json"</span>: &#123;</span><br><span class="line">    <span class="attr">"some"</span>: <span class="string">"data"</span></span><br><span class="line">  &#125;,  </span><br><span class="line">  <span class="attr">"url"</span>: <span class="string">"http://httpbin.org/post"</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>通过上述方法，我们可以POST JSON格式的数据 如果想要上传文件，那么直接用 file 参数即可 新建一个 a.txt 的文件，内容写上 Hello World!</p>
                  <figure class="highlight vim">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">'http://httpbin.org/post'</span></span><br><span class="line"><span class="keyword">files</span> = &#123;<span class="string">'file'</span>: <span class="keyword">open</span>(<span class="string">'test.txt'</span>, <span class="string">'rb'</span>)&#125;</span><br><span class="line">r = requests.post(url, <span class="keyword">files</span>=<span class="keyword">files</span>)</span><br><span class="line"><span class="keyword">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>可以看到运行结果如下</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"args"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"data"</span>: <span class="string">""</span>, </span><br><span class="line">  <span class="attr">"files"</span>: &#123;</span><br><span class="line">    <span class="attr">"file"</span>: <span class="string">"Hello World!"</span></span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">"form"</span>: &#123;&#125;, </span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Content-Length"</span>: <span class="string">"156"</span>, </span><br><span class="line">    <span class="attr">"Content-Type"</span>: <span class="string">"multipart/form-data; boundary=7d8eb5ff99a04c11bb3e862ce78d7000"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span></span><br><span class="line">  &#125;, </span><br><span class="line">  <span class="attr">"json"</span>: <span class="literal">null</span>, </span><br><span class="line">  <span class="attr">"url"</span>: <span class="string">"http://httpbin.org/post"</span></span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这样我们便成功完成了一个文件的上传。 requests 是支持流式上传的，这允许你发送大的数据流或文件而无需先把它们读入内存。要使用流式上传，仅需为你的请求体提供一个类文件对象即可</p>
                  <figure class="highlight livecodeserver">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">'massive-body'</span>) <span class="keyword">as</span> f:</span><br><span class="line">    requests.<span class="built_in">post</span>(<span class="string">'http://some.url/streamed'</span>, data=f)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>这是一个非常实用方便的功能。</p>
                  <h2 id="Cookies"><a href="#Cookies" class="headerlink" title="Cookies"></a>Cookies</h2>
                  <p>如果一个响应中包含了cookie，那么我们可以利用 cookies 变量来拿到</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">'http://example.com'</span></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(url)</span><br><span class="line"><span class="builtin-name">print</span> r.cookies</span><br><span class="line"><span class="builtin-name">print</span> r.cookies[<span class="string">'example_cookie_name'</span>]</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>以上程序仅是样例，可以用 cookies 变量来得到站点的 cookies 另外可以利用 cookies 变量来向服务器发送 cookies 信息</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">'http://httpbin.org/cookies'</span></span><br><span class="line">cookies = dict(<span class="attribute">cookies_are</span>=<span class="string">'working'</span>)</span><br><span class="line">r = requests.<span class="builtin-name">get</span>(url, <span class="attribute">cookies</span>=cookies)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight scilab">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="string">'&#123;"</span>cookies<span class="string">": &#123;"</span>cookies_are<span class="string">": "</span>working<span class="string">"&#125;&#125;'</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>可以已经成功向服务器发送了 cookies</p>
                  <h2 id="超时配置"><a href="#超时配置" class="headerlink" title="超时配置"></a>超时配置</h2>
                  <p>可以利用 timeout 变量来配置最大请求时间</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">requests.<span class="builtin-name">get</span>(<span class="string">'http://github.com'</span>, <span class="attribute">timeout</span>=0.001)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p><strong>注：timeout 仅对连接过程有效，与响应体的下载无关。</strong> 也就是说，这个时间只限制请求的时间。即使返回的 response 包含很大内容，下载需要一定时间，然而这并没有什么卵用。</p>
                  <h2 id="会话对象"><a href="#会话对象" class="headerlink" title="会话对象"></a>会话对象</h2>
                  <p>在以上的请求中，每次请求其实都相当于发起了一个新的请求。也就是相当于我们每个请求都用了不同的浏览器单独打开的效果。也就是它并不是指的一个会话，即使请求的是同一个网址。比如</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">requests.<span class="builtin-name">get</span>(<span class="string">'http://httpbin.org/cookies/set/sessioncookie/123456789'</span>)</span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">"http://httpbin.org/cookies"</span>)</span><br><span class="line"><span class="builtin-name">print</span>(r.text)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>结果是</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"cookies"</span>: &#123;&#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>很明显，这不在一个会话中，无法获取 cookies，那么在一些站点中，我们需要保持一个持久的会话怎么办呢？就像用一个浏览器逛淘宝一样，在不同的选项卡之间跳转，这样其实就是建立了一个长久会话。 解决方案如下</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">s = requests.Session()</span><br><span class="line">s.<span class="builtin-name">get</span>(<span class="string">'http://httpbin.org/cookies/set/sessioncookie/123456789'</span>)</span><br><span class="line">r = s.<span class="builtin-name">get</span>(<span class="string">"http://httpbin.org/cookies"</span>)</span><br><span class="line"><span class="builtin-name">print</span>(r.text)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>在这里我们请求了两次，一次是设置 cookies，一次是获得 cookies 运行结果</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"cookies"</span>: &#123;</span><br><span class="line">    <span class="attr">"sessioncookie"</span>: <span class="string">"123456789"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>发现可以成功获取到 cookies 了，这就是建立一个会话到作用。体会一下。 那么既然会话是一个全局的变量，那么我们肯定可以用来全局的配置了。</p>
                  <figure class="highlight pgsql">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">s = requests.<span class="keyword">Session</span>()</span><br><span class="line">s.headers.<span class="keyword">update</span>(&#123;<span class="string">'x-test'</span>: <span class="string">'true'</span>&#125;)</span><br><span class="line">r = s.<span class="keyword">get</span>(<span class="string">'http://httpbin.org/headers'</span>, headers=&#123;<span class="string">'x-test2'</span>: <span class="string">'true'</span>&#125;)</span><br><span class="line">print r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>通过 s.headers.update 方法设置了 headers 的变量。然后我们又在请求中设置了一个 headers，那么会出现什么结果？ 很简单，两个变量都传送过去了。 运行结果</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span>, </span><br><span class="line">    <span class="attr">"X-Test"</span>: <span class="string">"true"</span>, </span><br><span class="line">    <span class="attr">"X-Test2"</span>: <span class="string">"true"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>如果get方法传的headers 同样也是 x-test 呢？</p>
                  <figure class="highlight ini">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attr">r</span> = s.get(<span class="string">'http://httpbin.org/headers'</span>, headers=&#123;<span class="string">'x-test'</span>: <span class="string">'true'</span>&#125;)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>嗯，它会覆盖掉全局的配置</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span>, </span><br><span class="line">    <span class="attr">"X-Test"</span>: <span class="string">"true"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>那如果不想要全局配置中的一个变量了呢？很简单，设置为 None 即可</p>
                  <figure class="highlight ini">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="attr">r</span> = s.get(<span class="string">'http://httpbin.org/headers'</span>, headers=&#123;<span class="string">'x-test'</span>: None&#125;)</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>运行结果</p>
                  <figure class="highlight json">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"headers"</span>: &#123;</span><br><span class="line">    <span class="attr">"Accept"</span>: <span class="string">"*/*"</span>, </span><br><span class="line">    <span class="attr">"Accept-Encoding"</span>: <span class="string">"gzip, deflate"</span>, </span><br><span class="line">    <span class="attr">"Host"</span>: <span class="string">"httpbin.org"</span>, </span><br><span class="line">    <span class="attr">"User-Agent"</span>: <span class="string">"python-requests/2.9.1"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>嗯，以上就是 session 会话的基本用法</p>
                  <h2 id="SSL证书验证"><a href="#SSL证书验证" class="headerlink" title="SSL证书验证"></a>SSL证书验证</h2>
                  <p>现在随处可见 https 开头的网站，Requests可以为HTTPS请求验证SSL证书，就像web浏览器一样。要想检查某个主机的SSL证书，你可以使用 verify 参数 现在 12306 证书不是无效的嘛，来测试一下</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">'https://kyfw.12306.cn/otn/'</span>, <span class="attribute">verify</span>=<span class="literal">True</span>)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>结果</p>
                  <figure class="highlight css">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="selector-tag">requests</span><span class="selector-class">.exceptions</span><span class="selector-class">.SSLError</span>: <span class="selector-attr">[SSL: CERTIFICATE_VERIFY_FAILED]</span> <span class="selector-tag">certificate</span> <span class="selector-tag">verify</span> <span class="selector-tag">failed</span> (_<span class="selector-tag">ssl</span><span class="selector-class">.c</span><span class="selector-pseudo">:590)</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>果真如此 来试下 github 的</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">'https://github.com'</span>, <span class="attribute">verify</span>=<span class="literal">True</span>)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>嗯，正常请求，内容我就不输出了。 如果我们想跳过刚才 12306 的证书验证，把 verify 设置为 False 即可</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line">import requests</span><br><span class="line"></span><br><span class="line">r = requests.<span class="builtin-name">get</span>(<span class="string">'https://kyfw.12306.cn/otn/'</span>, <span class="attribute">verify</span>=<span class="literal">False</span>)</span><br><span class="line"><span class="builtin-name">print</span> r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>发现就可以正常请求了。在默认情况下 verify 是 True，所以如果需要的话，需要手动设置下这个变量。</p>
                  <h2 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h2>
                  <p>如果需要使用代理，你可以通过为任意请求方法提供 proxies 参数来配置单个请求</p>
                  <figure class="highlight nix">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="built_in">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="attr">proxies</span> = &#123;</span><br><span class="line">  <span class="string">"https"</span>: <span class="string">"http://41.118.132.69:4433"</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="attr">r</span> = requests.post(<span class="string">"http://httpbin.org/post"</span>, <span class="attr">proxies=proxies)</span></span><br><span class="line">print r.text</span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理</p>
                  <figure class="highlight routeros">
                    <table>
                      <tr>
                        <td class="gutter">
                          <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
                        </td>
                        <td class="code">
                          <pre><span class="line"><span class="builtin-name">export</span> <span class="attribute">HTTP_PROXY</span>=<span class="string">"http://10.10.1.10:3128"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">HTTPS_PROXY</span>=<span class="string">"http://10.10.1.10:1080"</span></span><br></pre>
                        </td>
                      </tr>
                    </table>
                  </figure>
                  <p>通过以上方式，可以方便地设置代理。</p>
                  <h2 id="API"><a href="#API" class="headerlink" title="API"></a>API</h2>
                  <p>以上讲解了 requests 中最常用的参数，如果需要用到更多，请参考官方文档 API <a href="http://docs.python-requests.org/en/master/api/" target="_blank" rel="noopener">API</a></p>
                  <h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2>
                  <p>以上总结了一下 requests 的基本用法，如果你对爬虫有了一定的基础，那么肯定可以很快上手，在此就不多赘述了。 练习才是王道，大家尽快投注于实践中吧。</p>
                  </p>
                </div>
              </div>
              <div class="post-meta">
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-user"></i>
                  </span>
                  <span class="post-meta-item-text">作者</span>
                  <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
                </span>
                <span class="post-meta-item">
                  <span class="post-meta-item-icon">
                    <i class="far fa-calendar"></i>
                  </span>
                  <span class="post-meta-item-text">发表于</span>
                  <time title="创建时间：2016-03-19 21:05:03" itemprop="dateCreated datePublished" datetime="2016-03-19T21:05:03+08:00">2016-03-19</time>
                </span>
                <span id="/2556.html" class="post-meta-item leancloud_visitors" data-flag-title="Python爬虫利器一之Requests库的用法" title="阅读次数">
                  <span class="post-meta-item-icon">
                    <i class="fa fa-eye"></i>
                  </span>
                  <span class="post-meta-item-text">阅读次数：</span>
                  <span class="leancloud-visitors-count"></span>
                </span>
                <span class="post-meta-item" title="本文字数">
                  <span class="post-meta-item-icon">
                    <i class="far fa-file-word"></i>
                  </span>
                  <span class="post-meta-item-text">本文字数：</span>
                  <span>7.2k</span>
                </span>
                <span class="post-meta-item" title="阅读时长">
                  <span class="post-meta-item-icon">
                    <i class="far fa-clock"></i>
                  </span>
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                  <span>7 分钟</span>
                </span>
              </div>
            </article>
            <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
              <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2529.html">
              <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
                <meta itemprop="image" content="/images/avatar.png">
                <meta itemprop="name" content="崔庆才">
                <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
              </span>
              <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
                <meta itemprop="name" content="静觅">
              </span>
              <header class="post-header">
                <h2 class="post-title" itemprop="name headline">
                  <a class="label"> JavaScript <i class="label-arrow"></i>
                  </a>
                  <a href="/2529.html" class="post-title-link" itemprop="url">jQuery易忽略的知识点总结</a>
                </h2>
              </header>
              <div class="post-body" itemprop="articleBody">
                <div class="thumb">
                  <img itemprop="contentUrl" class="random">
                </div>
                <div class="excerpt">
                  <p>
                  <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2>
                  <p>之前在用jQuery，不过有时候用着用着一些用法发现并没有用到过，比较陌生，现在重新梳理一下，把易忽略的知识点总结一下，长期更新。 参考梳理来源： <a href="http://www.imooc.com/learn/11" target="_blank" rel="noopener">慕课网</a></p>
                  <h2 id="sele1-sele2-seleN选择器"><a href="#sele1-sele2-seleN选择器" class="headerlink" title="sele1,sele2,seleN选择器"></a>sele1,sele2,seleN选择器</h2>
                  <p>有时需要精确的选择任意<strong>多个指定的元素</strong>，类似于从文具盒中挑选出多根自已喜欢的笔，就需要调用sele1,sele2,seleN选择器，它的调用格式如下： <code>$(“sele1,sele2,seleN”)</code> 其中参数sele1、sele2到seleN为有效选择器，每个选择器之间用“，”号隔开，它们可以是之前提及的各种类型选择器，如<code>$(“#id”)、$(“.class”)、$(“selector”)</code>选择器等。 例如，通过选择器获取其中的任意两个元素，并将它们显示的内容设为相同，如图所示： <a href="http://img.mukewang.com/528705b000012a1102890134.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/528705b000012a1102890134.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/528705c700010e6d04720207.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/528705c700010e6d04720207.jpg" alt=""></a> 虽然页面中添加了三个元素，但是通过使用<code>$(“div,p”)</code>选择器方式获取了其中的
                  <div>和<p>元素，并设置它们显示的内容。</p>
                    <h2 id="prev-next选择器"><a href="#prev-next选择器" class="headerlink" title="prev + next选择器"></a>prev + next选择器</h2>
                    <p>俗话说“远亲不如近邻”，而通过<code>prev + next</code>选择器就可以查找与“prev”元素紧邻的下一个“next”元素，格式如下： <code>$(“prev + next”)</code> 其中参数prev为任何有效的选择器，参数“next”为另外一个有效选择器，它们之间的“+”表示一种上下的层次关系，也就是说，“prev”元素最紧邻的下一个元素由“next”选择器返回的并且只返回唯的一个元素。 例如，使用<code>prev + next</code>选择器，获取
                    <p>元素最近邻的下一个元素，如下图所示： <a href="http://img.mukewang.com/5292e68c000191c204000224.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/5292e68c000191c204000224.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/5292ebe60001dc2b03350376.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/5292ebe60001dc2b03350376.jpg" alt=""></a></p>
                    <h2 id="prev-siblings选择器"><a href="#prev-siblings选择器" class="headerlink" title="prev ~ siblings选择器"></a>prev ~ siblings选择器</h2>
                    <p>与上一节中介绍的<code>prev + next</code>层次选择器相同，<code>prev ~ siblings</code>选择器也是查找prev 元素之后的相邻元素，但前者只获取第一个相邻的元素，而后者则获取prev 元素后面全部相邻的元素，它的调用格式如下： <code>$(“prev ~ siblings”)</code> 其中参数prev与siblings两者之间通过“~”符号形成一种层次相邻的关系，表明siblings选择器获取的元素都是prev元素之后的同辈元素。 例如，使用<code>prev ~ next</code>选择器，获取
                    <p>元素后面相邻的全部元素，并设置它们在页面中显示的内容，如下图所示： <a href="http://img.mukewang.com/5292fc460001105a03310216.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/5292fc460001105a03310216.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/5292fc690001e15d04200411.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/5292fc690001e15d04200411.jpg" alt=""></a> 可以看出，调用<code>$(&quot;p~span&quot;)</code>选择器代码，获取了
                    <p>元素下面两个(全部)的<span>元素，该元素不包含<p>元素上面的元素和不属于同辈范围的元素。</p>
                        <h2 id="contains-text-过滤选择器"><a href="#contains-text-过滤选择器" class="headerlink" title=":contains(text)过滤选择器"></a>:contains(text)过滤选择器</h2>
                        <p>与上一节介绍的:eq(index)选择器按索引查找元素相比，有时候我们可能希望按照<strong>文本内容</strong>来查找一个或多个元素，那么使用<code>:contains(text)</code>选择器会更加方便， 它的功能是选择<strong>包含</strong>指定字符串的全部元素，它通常与其他元素结合使用，获取包含“text”字符串内容的全部元素对象。其中参数<code>text</code>表示页面中的文字。 例如: <a href="http://img.mukewang.com/529c067b00014cad03480210.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c067b00014cad03480210.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/529c069b0001879204890294.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c069b0001879204890294.jpg" alt=""></a> 从图中可以看出，调用<code>li:contains(&#39;土豪&#39;)</code>代码，可以很方便地获取<li>中<strong>包含</strong>‘土豪’字符内容的全部元素，并且只要与选择的元素中或子元素中包含该字符内容，就可以被选中。 注意：<code>li:contains(&#39;土豪&#39;)</code> 土豪为什么必须加单引号呢？因为它是一个字符串，而不是一个变量，所以不加单或双引号的话是会报错的。</p>
                        <h2 id="has-selector-过滤选择器"><a href="#has-selector-过滤选择器" class="headerlink" title=":has(selector)过滤选择器"></a>:has(selector)过滤选择器</h2>
                        <p>除了在上一小节介绍的使用包含的字符串内容过滤元素之外，还可以使用包含的元素名称来过滤，<code>:has(selector)</code>过滤选择器的功能是获取选择器中包含指定元素名称的全部元素，其中<code>selector</code>参数就是包含的元素名称，是被包含元素。 例如：获取指定包含某个元素名的全部<li>元素，并改变它们显示文字的颜色，如下图所示： <a href="http://img.mukewang.com/529c1a8300017dd003040210.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c1a8300017dd003040210.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/529c1aab00017a4d04890294.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c1aab00017a4d04890294.jpg" alt=""></a> 可以看出，通过使用<code>$(&quot;li:has(&#39;p&#39;)&quot;)</code>选择器代码，获取了包含<p>元素的全部
                          <li>元素，并通过css方法改变了这些元素在页面中显示的文字样式。
                        </p>
                        <h2 id="hidden过滤选择器"><a href="#hidden过滤选择器" class="headerlink" title=":hidden过滤选择器"></a>:hidden过滤选择器</h2>
                        <p><code>:hidden</code>过滤选择器的功能是获取全部不可见的元素，这些不可见的元素中包括type属性值为hidden的元素。 例如，调用<code>:hidden</code>选择器获取不可见的
                        <p>元素，并将该元素的内容显示在
                        <div>元素中，如下图所示： <a href="http://img.mukewang.com/529c1c5a00011bc303620165.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c1c5a00011bc303620165.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/529c1c760001eaf304890212.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c1c760001eaf304890212.jpg" alt=""></a> 从图中可以看出，先调用<code>$(&quot;p:hidden&quot;)</code>代码获取隐藏的<p>元素，并调用该元素的html()方法获取该元素中的内容，最后将该内容显示在
                          <div>元素中。</p>
                    <h2 id="visible过滤选择器"><a href="#visible过滤选择器" class="headerlink" title=":visible过滤选择器"></a>:visible过滤选择器</h2>
                    <p>与上一节的<code>:hidden</code>过滤选择器相反，<code>:visible</code>过滤选择器获取的是全部可见的元素，也就是说，只要不将元素的display属性值设置为“none”，那么，都可以通过该选择器获取。 例如，使用<code>:visible</code>选择器获取可见的
                    <p>元素，并将该元素的内容显示在
                    <div>元素中，如下图所示： <a href="http://img.mukewang.com/529c2106000192f303620159.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c2106000192f303620159.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/529c212000016e8e04890193.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c212000016e8e04890193.jpg" alt=""></a> 从图中可以看出，调用<code>$(&quot;p:visible&quot;)</code>选择器代码，获取那个可见的<p>元素，并调用<code>html()</code>方法获取该元素的内容，最后将该内容显示在
                      <div>元素中。</p>
                        <h2 id="input表单选择器"><a href="#input表单选择器" class="headerlink" title=":input表单选择器"></a>:input表单选择器</h2>
                        <p>如何获取表单全部元素？<code>:input</code>表单选择器可以实现，它的功能是返回<strong>全部的表单元素</strong>，不仅包括所有<input>标记的表单元素，而且还包括<textarea>、<select> 和 <button>标记的表单元素，因此，它选择的表单元素是最广的。 如下图所示，使用<code>:input</code>表单选择器获取表单元素，并向这些元素增加一个CSS样式类别，修改它们在页面中显示的边框颜色。 <img src="http://img.mukewang.com/52970dc4000102ab03820242.jpg" alt=""> 在浏览器中显示的效果： <img src="http://img.mukewang.com/52970dd300016ac304760305.jpg" alt=""> 可以看出，通过调用$(“#frmTest :input”)表单选择器代码获取了表单中的全部元素，并使用addClass()方法修改它们在页面中显示的边框颜色。addClass()方法的功能是为元素添加指定的样式类别名称，它的更多使用将会在后续章节中进行详细介绍。</p>
<h2 id="text表单文本选择器"><a href="#text表单文本选择器" class="headerlink" title=":text表单文本选择器"></a>:text表单文本选择器</h2><p><code>:text</code>表单文本选择器可以获取表单中全部单行的文本输入框元素，单行的文本输入框就像一个不换行的字条工具，使用非常广泛。 例如，在表单中添加多个元素，使用<code>:text</code>选择器获取单行的文本输入框元素，并修改字的边框颜色，如下图所示： <img src="http://img.mukewang.com/5297107600011ddf04240201.jpg" alt=""> 在浏览器中显示的效果： <img src="http://img.mukewang.com/52971086000125ea04440275.jpg" alt=""> 从图中可以看出，通过<code>:text</code>表单选择器只获取单行的文本输入框元素，对于<textarea>区域文本、按钮元素无效。</p>
<h2 id="password表单密码选择器"><a href="#password表单密码选择器" class="headerlink" title=":password表单密码选择器"></a>:password表单密码选择器</h2><p>如果想要获取密码输入文本框，可以使用<code>:password</code>选择器，它的功能是获取表单中全部的密码输入文本框元素。 例如，在表单中添加多个输入框元素，使用<code>:password</code>获取密码输入文本框元素，并修改它的边框颜色，如下图所示： <img src="http://img.mukewang.com/529713cd000159b804810217.jpg" alt=""> 在浏览器中显示的效果： <img src="http://img.mukewang.com/529713e50001b30004510309.jpg" alt=""> 从图中可以看出，在多个文本输入框中，使用:password选择器只能获取表单中的密码输入文本框，并使用addClass()方法改变它的边框颜色。</p>
<h2 id="radio单选按钮选择器"><a href="#radio单选按钮选择器" class="headerlink" title=":radio单选按钮选择器"></a>:radio单选按钮选择器</h2><p>表单中的单选按钮常用于多项数据中仅选择其一，而使用<code>:radio</code>选择器可轻松获取表单中的<strong>全部单选按钮</strong>元素。 例如，在表单中添加多种类型的表单元素，使用<code>:radio</code>选择器获取并隐藏这些元素中的全部单选按钮元素，如下图所示： <img src="http://img.mukewang.com/529715580001099503830280.jpg" alt=""> <code>hide()</code>方法的功能是隐藏指定的元素。 在浏览器中显示的效果： <img src="http://img.mukewang.com/529715c60001ca0504500321.jpg" alt=""> 以上是:radio选择器的效果。</p>
<h2 id="checkbox复选框选择器"><a href="#checkbox复选框选择器" class="headerlink" title=":checkbox复选框选择器"></a>:checkbox复选框选择器</h2><p>表单中的复选框常用于多项数据的选择，使用<code>:checkbox</code>选择器可以快速定位并获取表单中的复选框元素。 例如，在表单中增加多个不同类型的元素，使用<code>:checkbox</code>选择器获取其中的全部复选框元素，并将它们全部设为选中状态，如下图所示： <a href="http://img.mukewang.com/52971ac700017fbf03830322.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52971ac700017fbf03830322.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52971afe0001750304500280.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52971afe0001750304500280.jpg" alt=""></a> 这样便实现了选中 checkbox 的效果，做<strong>全选</strong>的时候比较方便。</p>
<h2 id="submit提交按钮选择器"><a href="#submit提交按钮选择器" class="headerlink" title=":submit提交按钮选择器"></a>:submit提交按钮选择器</h2><p>通常情况下，一个表单中只允许有一个“type”属性值为“submit”的提交按钮，使用<code>:submit</code>选择器可获取表单中的这个<strong>提交按钮</strong>元素。 例如，在表单中添加多个不同类型的按钮，使用<code>:submit</code>选择器获取其中的提交按钮，并使用<code>attr()</code>方法修改按钮显示的文本内容，如下图所示： <a href="http://img.mukewang.com/52b2584e000129a804330199.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b2584e000129a804330199.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52b258c60001e23604500280.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b258c60001e23604500280.jpg" alt=""></a> 从图中可以看出，使用<code>:submit</code>选择器从三种类型按钮中获取了提交按钮，并使用<code>attr()</code>方法将该按钮显示的文字修改为“点我就提交了”。</p>
<h2 id="button表单按钮选择器"><a href="#button表单按钮选择器" class="headerlink" title=":button表单按钮选择器"></a>:button表单按钮选择器</h2><p>表单中包含许多类型的按钮，而使用<code>:button</code>选择器能获取且只能获取“type”属性值为“button”的<input>和<button>这两类普通按钮元素。 例如，在表单中添加多种类型的按钮元素，使用<code>:button</code>选择器获取其中的普通按钮元素，并修改它们的边框色，如下图所示： <a href="http://img.mukewang.com/52b286a50001862e04740207.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b286a50001862e04740207.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52b286e100017beb04530252.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b286e100017beb04530252.jpg" alt=""></a> 从图中可以看出，使用<code>:button</code>选择器只能获取两种类型的普通按钮，且修改了它们的边框颜色，并未获取表单中的“提交按钮”。</p>
<h2 id="checked选中状态选择器"><a href="#checked选中状态选择器" class="headerlink" title=":checked选中状态选择器"></a>:checked选中状态选择器</h2><p>有一些元素存在选中状态，如复选框、单选按钮元素，选中时“checked”属性值为“checked”，调用:checked可以获取处于选中状态的全部元素。 例如，在表单中添加多个复选框和单选按钮，其中有一些元素处于选中状态，使用<code>:checked</code><strong>获取</strong>并<strong>隐藏</strong>处于选中状态的元素，如下图所示： <a href="http://img.mukewang.com/52b28b1500017db404530386.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b28b1500017db404530386.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52b28b3b00015c7f04500290.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b28b3b00015c7f04500290.jpg" alt=""></a> 从图中可以看出，使用<code>:checked</code>选择器可以获取处于选中状态的元素，并调用<code>hide()</code>方法将它们进行隐藏。</p>
<h2 id="selected选中状态选择器"><a href="#selected选中状态选择器" class="headerlink" title=":selected选中状态选择器"></a>:selected选中状态选择器</h2><p>与<code>:checked</code>选择器相比，<code>:selected</code>选择器只能获取<select>下拉列表框中全部处于选中状态的<option>选项元素。 例如，在一个添加多个<option>选项的下拉列表框中，使用<code>:selected</code>选择器修改处于选中状态的内容值，如下图所示： <a href="http://img.mukewang.com/52b28d15000198f404430262.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b28d15000198f404430262.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52b28d370001a09004570304.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52b28d370001a09004570304.jpg" alt=""></a> 从图中可以看出，使用<code>:selected</code>选择器获取处于选中状态的<option>元素，并调用<code>text()</code>方法修改这些选中状态元素显示的内容。<code>text()</code>方法的功能是获取或设置元素的文本内容，该方法在后续将有详细的介绍。</p>
<h2 id="first-child子元素过滤选择器"><a href="#first-child子元素过滤选择器" class="headerlink" title=":first-child子元素过滤选择器"></a>:first-child子元素过滤选择器</h2><p>通过上面章节的学习，我们知道使用<code>:first</code>过滤选择器可以获取指定父元素中的首个子元素，但该选择器返回的只有一个元素，并不是一个集合，而使用<code>:first-child</code>子元素过滤选择器则可以获取每个父元素中返回的首个子元素，它是一个集合，常用多个集合数据的选择处理。 如下图，如果想把页面中每个ul中的第一个li获取到，并改变其颜色。则可以使用 <code>: first-child</code> <a href="http://img.mukewang.com/529c2a9000014a0e03500322.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c2a9000014a0e03500322.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/529c2ab600011b5804890326.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/529c2ab600011b5804890326.jpg" alt=""></a> 通过<code>$(&quot;li:first-child&quot;)</code>选择器代码，获取了两个<ul>父元素中的第一个<li>元素，并使用<code>css()</code>方法修改了它们在页面中显示的文字颜色。</p>
<h2 id="替换内容"><a href="#替换内容" class="headerlink" title="替换内容"></a>替换内容</h2><p><code>replaceWith()</code>和<code>replaceAll()</code>方法都可以用于替换元素或元素中的内容，但它们调用时，内容和被替换元素所在的位置不同，分别为如下所示： <code>**$(selector).replaceWith(content)**</code>和<code>**$(content).replaceAll(selector)**</code> 参数selector为被替换的元素，content为替换的内容。 例如，调用<code>replaceWith()</code>方法将页面中<span>元素替换成一段HTML字符串，如下图所示： <a href="http://img.mukewang.com/52bcdc2c0001b69c04750130.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bcdc2c0001b69c04750130.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52bcdc4f0001e25f04830237.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bcdc4f0001e25f04830237.jpg" alt=""></a> 从图中可以看出，使用<code>replaceWith()</code>方法替换类别名为“green”的<span>元素，替换之后，旧元素完全由新替换的元素所取代。</p>
<h2 id="使用wrap-和wrapInner-方法包裹元素和内容"><a href="#使用wrap-和wrapInner-方法包裹元素和内容" class="headerlink" title="使用wrap()和wrapInner()方法包裹元素和内容"></a>使用wrap()和wrapInner()方法包裹元素和内容</h2><p><code>wrap()</code>和<code>wrapInner()</code>方法都可以进行元素的包裹，但前者用于包裹元素本身，后者则用于包裹元素中的内容，它们的调用格式分别为： <code>**$(selector).wrap(wrapper)**</code>和<code>**$(selector).wrapInner(wrapper)**</code> 参数selector为被包裹的元素，wrapper参数为包裹元素的格式。 例如，调用<code>wrap()</code>方法，将<span>用<div>元素包裹起来，如下图所示： <a href="http://img.mukewang.com/52bcdea700016dbf03980120.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bcdea700016dbf03980120.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52bcdf080001301504830245.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bcdf080001301504830245.jpg" alt=""></a> 从图中可以看出，红色区域的<span>元素被蓝色边框的<div>元素通过<code>wrap()</code>方法包裹起来</p>
<h2 id="使用remove-和empty-方法删除元素"><a href="#使用remove-和empty-方法删除元素" class="headerlink" title="使用remove()和empty()方法删除元素"></a>使用remove()和empty()方法删除元素</h2><p><code>remove()</code>方法删除所选元素本身和子元素，该方法可以通过添加过滤参数指定需要删除的某些元素，而<code>empty()</code>方法则只删除所选元素的子元素。 例如，调用<code>remove()</code>方法删除<span>元素中类别名为“red”的，如下图所示： <a href="http://img.mukewang.com/52bceff500018e0702910171.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bceff500018e0702910171.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52bcf01c00013b5004830297.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52bcf01c00013b5004830297.jpg" alt=""></a> 从图中可以看出，使用<code>remove(&quot;.red&quot;)</code>方法只是把<span>元素中类别名为“red”的这部分元素给删除了。</p>
<h2 id="使用hover-方法切换事件"><a href="#使用hover-方法切换事件" class="headerlink" title="使用hover()方法切换事件"></a>使用hover()方法切换事件</h2><p><code>hover()</code>方法的功能是当鼠标移到所选元素上时，执行方法中的第一个函数，鼠标移出时，执行方法中的第二个函数，实现事件的切实效果，调用格式如下： <code>**$(selector).hover(over****，****out);**</code> over参数为移到所选元素上触发的函数，out参数为移出元素时触发的函数。 例如，当鼠标移到<div>元素上时，元素中的字体变成金黄色，如下图所示： <a href="http://img.mukewang.com/52d22c9900013dbd03190241.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d22c9900013dbd03190241.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52d22cba0001163f04670262.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d22cba0001163f04670262.jpg" alt=""></a> 从图中可以看出，使用<code>hover()</code>方法执行两个函数，当鼠标移在元素上时调用<code>addClass()</code>方法增加一个样式，移出时，调用<code>removeClass()</code>方法移除该样式。</p>
<h2 id="使用toggle-方法绑定多个函数"><a href="#使用toggle-方法绑定多个函数" class="headerlink" title="使用toggle()方法绑定多个函数"></a>使用toggle()方法绑定多个函数</h2><p><code>toggle()</code>方法可以在元素的click事件中绑定两个或两个以上的函数，同时，它还可以实现元素的隐藏与显示的切换，绑定多个函数的调用格式如下： <code>**$(selector).toggle(fun1(),fun2(),funN(),...)**</code> 其中，fun1，fun2就是多个函数的名称 例如，使用<code>toggle()</code>方法，当每次点击<div>元素时，显示不同内容，如下图所示： <a href="http://img.mukewang.com/52d22e3a0001c56d02980289.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d22e3a0001c56d02980289.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52d22e570001902a04670335.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d22e570001902a04670335.jpg" alt=""></a> 从图中可以看出，每次点击<div>元素时，都依次执行<code>toggle()</code>方法绑定的函数，当执行到最后一个函数时，再次点击将又返回执行第一个函数。 注意：toggle()方法支持目前主流稳定的jQuery版本1.8.2，在1.9.0之后的版本是不支持的。</p>
<h2 id="使用one-方法绑定元素的一次性事件"><a href="#使用one-方法绑定元素的一次性事件" class="headerlink" title="使用one()方法绑定元素的一次性事件"></a>使用one()方法绑定元素的一次性事件</h2><p><code>one()</code>方法可以绑定元素任何有效的事件，但这种方法绑定的事件只会触发一次，它的调用格式如下： <code>**$(selector).one(event,[data],fun)**</code> 参数event为事件名称，data为触发事件时携带的数据，fun为触发该事件时执行的函数。 例如，使用one方法绑定<div>元素的单击事件，在事件执行的函数中，累计执行的次数，并将该次数显示在页面中，如下图所示： <a href="http://img.mukewang.com/52d231bd000192fb04310219.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d231bd000192fb04310219.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52d231dd00011da004890293.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52d231dd00011da004890293.jpg" alt=""></a> 从图中可以看出，由于使用了<code>one()</code>方法绑定<div>元素的单击事件，因为事件函数只能执行一次，执行完成后，无论如何单击，都不再触发。</p>
<h2 id="调用animate-方法制作移动位置的动画"><a href="#调用animate-方法制作移动位置的动画" class="headerlink" title="调用animate()方法制作移动位置的动画"></a>调用animate()方法制作移动位置的动画</h2><p>调用<code>animate()</code>方法不仅可以制作简单渐渐变大的动画效果，而且还能制作移动位置的动画，在移动位置之前，必须将被移元素的“position”属性值设为“absolute”或“relative”，否则，该元素移动不了。 例如，调用<code>animate()</code>方法先将图片向右移动90px，然后，再将图片宽度与高度分别增加30px，如下图所示： <a href="http://img.mukewang.com/52dcc4eb0001c08e03410291.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52dcc4eb0001c08e03410291.jpg" alt=""></a> 在浏览器中显示的效果： <a href="http://img.mukewang.com/52dcc50b0001ba2205060337.jpg" target="_blank" rel="noopener"><img src="http://img.mukewang.com/52dcc50b0001ba2205060337.jpg" alt=""></a> 从图中可以看出，图片先向右移动了“90px”，然后，移动成功后，再在原来的基础之上以动画的效果增大30px，增加成功后，显示“执行完成！”的字样。</p>
<p>s</p>
</p>
      
    </div>

  </div>

  
  
  

  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2016-03-16 14:12:32" itemprop="dateCreated datePublished"
            datetime="2016-03-16T14:12:32+08:00">2016-03-16</time>
    </span>

    
    <span id="/2529.html" class="post-meta-item leancloud_visitors" data-flag-title="jQuery易忽略的知识点总结"
          title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
        <span class="post-meta-item-text">本文字数：</span>
      <span>6.2k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
        <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>6 分钟</span>
    </span>

  </div>

</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2491.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Other <i class="label-arrow"></i>
      </a>
      <a href="/2491.html" class="post-title-link" itemprop="url">PhpStorm使用File Watchers自动编译less</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="综述"><a href="#综述" class="headerlink" title="综述"></a>综述</h2>
      <p>PhpStorm可以使用File Watchers自动编译Less，有了这个IDE，妈妈再也不用担心我的Less编译了。下面说一下我的配置过程。 下面的例子以 Mac OS X为例。</p>
      <h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2>
      <h3 id="1-配置npm"><a href="#1-配置npm" class="headerlink" title="1.配置npm"></a>1.配置npm</h3>
      <figure class="highlight mipsasm">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">brew </span><span class="keyword">install </span>npm</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>更多平台安装方式 <a href="https://www.npmjs.com/" target="_blank" rel="noopener">npm</a></p>
      <h3 id="2-安装lessc"><a href="#2-安装lessc" class="headerlink" title="2.安装lessc"></a>2.安装lessc</h3>
      <figure class="highlight cmake">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">npm <span class="keyword">install</span> <span class="keyword">less</span> -g</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>安装完毕后查看安装路径</p>
      <figure class="highlight bash">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="built_in">which</span> lessc</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>Mac OS X的结果是</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="regexp">/usr/</span>local<span class="regexp">/bin/</span>lessc</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <h3 id="3-配置PhpStorm"><a href="#3-配置PhpStorm" class="headerlink" title="3.配置PhpStorm"></a>3.配置PhpStorm</h3>
      <p>打开PhpStorm，Preferences-&gt;Tools-&gt;File Watchers 点击加号新增 Less Template，然后点击编辑按钮编辑，页面如下 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/56926F1E-D626-4E66-925D-15971F993F30.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/56926F1E-D626-4E66-925D-15971F993F30-1024x557.jpg" alt="56926F1E-D626-4E66-925D-15971F993F30"></a> 其中需要配置两个地方</p>
      <h4 id="Program："><a href="#Program：" class="headerlink" title="Program："></a>Program：</h4>
      <p>配置为lessc的路径，这边配置为 /usr/local/bin/lessc</p>
      <h4 id="Output-paths-to-refresh："><a href="#Output-paths-to-refresh：" class="headerlink" title="Output paths to refresh："></a>Output paths to refresh：</h4>
      <figure class="highlight groovy">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">$FileParentDir(less)<span class="string">$/css/$</span>FileDirPathFromParent(less)<span class="string">$/$FileNameWithoutExtension$.css</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>在这里简单解释下这个路径的意思。</p>
      <blockquote>
        <p>例如项目名为 project，less文件我们放置在 project/public/less/manage/style.less $FileParentDir(less)$ 是获取 less 目录的路径，也就是 project/public $FileDirPathFromParent(less)$ 是获取 less 文件到 less 目录的路径，也就是 manage $FileNameWithoutExtension$ 是获取 less 文件不带后缀的名字，也就是 style 经过如上拼接，生成的内容为 project/public/css/manage/style.css</p>
      </blockquote>
      <p>所以，不论我们的 less 文件如何放置，都可以生成相对路径的 css 文件。 配置完成之后，我们新建 less 目录，任意编辑一个 less 文件，都会在 css 目录下生成相应的文件。</p>
      <h2 id="简单配置"><a href="#简单配置" class="headerlink" title="简单配置"></a>简单配置</h2>
      <p>当然，如果你的 less 文件就直接在 less 目录下，可以简单配置以上的 Output Path如下 ../css/$FileNameWithoutExtension$.css 这也是一种比较常用的配置方法。 如果目录结构简单，可以采取以上方式。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-25 14:16:39" itemprop="dateCreated datePublished" datetime="2016-02-25T14:16:39+08:00">2016-02-25</time>
    </span>
    <span id="/2491.html" class="post-meta-item leancloud_visitors" data-flag-title="PhpStorm使用File Watchers自动编译less" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>949</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2469.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> JavaScript <i class="label-arrow"></i>
      </a>
      <a href="/2469.html" class="post-title-link" itemprop="url">JavaScript与jQuery基本用法总结</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h2>
      <ol>
        <li><a href="http://cuiqingcai.com/1253.html">JavaScript高级用法一之事件响应与网页交互</a> 2. <a href="http://cuiqingcai.com/1257.html">JavaScript高级用法二之内置对象</a> 3. <a href="http://cuiqingcai.com/1263.html">JavaScript高级用法三之浏览器对象</a> 4. <a href="http://cuiqingcai.com/1278.html">JavaScript高级用法四之DOM对象</a> 5. <a href="http://cuiqingcai.com/1444.html">JavaScript高级用法五之常用对象</a></li>
      </ol>
      <h2 id="jQuery"><a href="#jQuery" class="headerlink" title="jQuery"></a>jQuery</h2>
      <ol>
        <li><a href="http://cuiqingcai.com/1544.html">jQuery应用一之验证插件validate的使用</a> 2. <a href="http://cuiqingcai.com/1573.html">jQuery应用二之邮箱下拉列表自动补全</a> 3. <a href="http://cuiqingcai.com/1585.html">jQuery应用三之图片浏览插件LightBox</a> 4. <a href="http://cuiqingcai.com/1592.html">jQuery应用四之图片局部放大插件jQZoom</a> 5. <a href="http://cuiqingcai.com/1680.html">jQuery应用五之瀑布流效果的实现</a></li>
      </ol>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-11 21:50:19" itemprop="dateCreated datePublished" datetime="2016-02-11T21:50:19+08:00">2016-02-11</time>
    </span>
    <span id="/2469.html" class="post-meta-item leancloud_visitors" data-flag-title="JavaScript与jQuery基本用法总结" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>250</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2467.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> C/C++ <i class="label-arrow"></i>
      </a>
      <a href="/2467.html" class="post-title-link" itemprop="url">OpenGL绘图学习总结</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="目录索引"><a href="#目录索引" class="headerlink" title="目录索引"></a>目录索引</h2>
      <ol>
        <li><a href="http://cuiqingcai.com/1597.html">OpenGL绘图实例一之机器人的绘制</a> 2. <a href="http://cuiqingcai.com/1613.html">OpenGL绘图实例二之直线和圆弧的绘制</a> 3. O<a href="http://cuiqingcai.com/1640.html">penGL绘图实例三之种子填充算法</a> 4. <a href="http://cuiqingcai.com/1649.html">OpenGL绘图实例四之区域颜色填充</a> 5. <a href="http://cuiqingcai.com/1658.html">OpenGL绘图实例五之平移缩放旋转</a> 6. <a href="http://cuiqingcai.com/1776.html">OpenGL绘图实例六之鼠标监听事件</a> 7. <a href="http://cuiqingcai.com/1783.html">OpenGL绘图实例七之鼠标设色取点绘图</a> 7. <a href="http://cuiqingcai.com/1802.html">OpenGL绘图实例八之图形的移动删除存盘</a> 9. <a href="http://cuiqingcai.com/1860.html">OpenGL绘图实例九之3D绘图基础</a> 10. <a href="http://cuiqingcai.com/1867.html">OpenGL绘图实例十之绘制3D机器人</a></li>
      </ol>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-11 21:42:24" itemprop="dateCreated datePublished" datetime="2016-02-11T21:42:24+08:00">2016-02-11</time>
    </span>
    <span id="/2467.html" class="post-meta-item leancloud_visitors" data-flag-title="OpenGL绘图学习总结" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>211</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2465.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> C/C++ <i class="label-arrow"></i>
      </a>
      <a href="/2465.html" class="post-title-link" itemprop="url">Winpcap网络编程学习探究</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="目录索引"><a href="#目录索引" class="headerlink" title="目录索引"></a>目录索引</h2>
      <p>1. <a href="http://cuiqingcai.com/1890.html">Winpcap网络编程一之前言，实验要求，实验目标</a> 2. <a href="http://cuiqingcai.com/1898.html">Winpcap网络编程二之环境配置，Eclipse配置C/C++环境</a> 3. <a href="http://cuiqingcai.com/1906.html">Winpcap网络编程三之环境配置，Eclipse配置Winpcap环境</a> 4. <a href="http://cuiqingcai.com/1913.html">Winpcap网络编程四之环境配置，VS配置Winpcap环境</a> 5. <a href="http://cuiqingcai.com/1918.html">Winpcap网络编程五之ARP协议获得MAC表及主机通信</a> 6. <a href="http://cuiqingcai.com/1922.html">Winpcap网络编程六之两台主机通过中间主机通信</a></p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-11 21:27:53" itemprop="dateCreated datePublished" datetime="2016-02-11T21:27:53+08:00">2016-02-11</time>
    </span>
    <span id="/2465.html" class="post-meta-item leancloud_visitors" data-flag-title="Winpcap网络编程学习探究" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>196</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2443.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Python <i class="label-arrow"></i>
      </a>
      <a href="/2443.html" class="post-title-link" itemprop="url">Python爬虫进阶二之PySpider框架安装配置</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="关于"><a href="#关于" class="headerlink" title="关于"></a>关于</h2>
      <p>首先，在此附上项目的地址，以及官方文档 <a href="https://github.com/binux/pyspider" target="_blank" rel="noopener">PySpider</a> <a href="http://docs.pyspider.org/en/latest/" target="_blank" rel="noopener">官方文档</a></p>
      <h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2>
      <h3 id="1-pip"><a href="#1-pip" class="headerlink" title="1. pip"></a>1. pip</h3>
      <p>首先确保你已经安装了pip，若没有安装，请参照 <a href="http://pip-cn.readthedocs.org/en/latest/installing.html" target="_blank" rel="noopener">pip安装</a></p>
      <h3 id="2-phantomjs"><a href="#2-phantomjs" class="headerlink" title="2. phantomjs"></a>2. phantomjs</h3>
      <p>PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API。它全面支持web而不需浏览器支持，其快速、原生支持各种Web标准：DOM 处理、CSS 选择器、JSON、Canvas 和 SVG。 PhantomJS 可以用于页面自动化、网络监测、网页截屏以及无界面测试等。 <a href="http://phantomjs.org/download.html" target="_blank" rel="noopener">安装</a> 以上附有官方安装方式，如果你是 Ubuntu 或 Mac OS X用户，可以直接用命令来安装 Ubuntu:</p>
      <figure class="highlight routeros">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo apt-<span class="builtin-name">get</span> install phantomjs</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>Mac OS X:</p>
      <figure class="highlight mipsasm">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">brew </span><span class="keyword">install </span>phantomjs</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <h3 id="3-pyspider"><a href="#3-pyspider" class="headerlink" title="3. pyspider"></a>3. pyspider</h3>
      <p>直接利用 pip 安装即可</p>
      <figure class="highlight cmake">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">pip <span class="keyword">install</span> pyspider</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>如果你是 Ubuntu 用户，请提前安装好以下支持类库</p>
      <figure class="highlight vim">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo apt-<span class="built_in">get</span> install <span class="keyword">python</span> <span class="keyword">python</span>-dev <span class="keyword">python</span>-distribute <span class="keyword">python</span>-pip libcurl4-openssl-dev libxml2-dev libxslt1-dev <span class="keyword">python</span>-lxml</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>测试 如果安装过程没有提示任何错误，那就证明一些OK。 命令行输入</p>
      <figure class="highlight ada">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">pyspider <span class="keyword">all</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后浏览器访问 <a href="http://localhost:5000" target="_blank" rel="noopener">http://localhost:5000</a> 观察一下效果，如果可以正常出现 PySpider 的页面，那证明一切OK 在此附图一张，这是我写了几个爬虫之后的界面。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/2016-02-11-20.55.36.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/2016-02-11-20.55.36-1024x355.png" alt="2016-02-11 20.55.36"></a> 好，接下来我会进一步介绍这个框架的使用。</p>
      <h2 id="常见错误"><a href="#常见错误" class="headerlink" title="常见错误"></a>常见错误</h2>
      <p>我曾遇到过的一个错误： <a href="http://cuiqingcai.com/2703.html">PySpider HTTP 599: SSL certificate problem错误的解决方法</a> ，后来在作者那发了issue得到了答案，其他的暂时没什么问题。 不过发现有的小伙伴提了各种各样的问题啊，不过我确实都没遇到过，我再Win10，Linux Ubuntu，Linux CentOS，Mac OS X都成功运行。不过确实有些奇怪的问题，跑着跑着崩了，一点就崩了我也就比较纳闷了。 如果大家有问题，可以看看作者项目里面有没有类似的issue，另外也推荐大家直接到作者的GitHub上发issue。 毕竟，这个框架不是我写的。 在此附上Issue地址： <a href="https://github.com/binux/pyspider/issues" target="_blank" rel="noopener">PySpider Issue</a></p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-11 21:00:04" itemprop="dateCreated datePublished" datetime="2016-02-11T21:00:04+08:00">2016-02-11</time>
    </span>
    <span id="/2443.html" class="post-meta-item leancloud_visitors" data-flag-title="Python爬虫进阶二之PySpider框架安装配置" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>944</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2433.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Python <i class="label-arrow"></i>
      </a>
      <a href="/2433.html" class="post-title-link" itemprop="url">Python爬虫进阶一之爬虫框架概述</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="综述"><a href="#综述" class="headerlink" title="综述"></a>综述</h2>
      <p>爬虫入门之后，我们有两条路可以走。 一个是继续深入学习，以及关于设计模式的一些知识，强化Python相关知识，自己动手造轮子，继续为自己的爬虫增加分布式，多线程等功能扩展。另一条路便是学习一些优秀的框架，先把这些框架用熟，可以确保能够应付一些基本的爬虫任务，也就是所谓的解决温饱问题，然后再深入学习它的源码等知识，进一步强化。 就个人而言，前一种方法其实就是自己动手造轮子，前人其实已经有了一些比较好的框架，可以直接拿来用，但是为了自己能够研究得更加深入和对爬虫有更全面的了解，自己动手去多做。后一种方法就是直接拿来前人已经写好的比较优秀的框架，拿来用好，首先确保可以完成你想要完成的任务，然后自己再深入研究学习。第一种而言，自己探索的多，对爬虫的知识掌握会比较透彻。第二种，拿别人的来用，自己方便了，可是可能就会没有了深入研究框架的心情，还有可能思路被束缚。 不过个人而言，我自己偏向后者。造轮子是不错，但是就算你造轮子，你这不也是在基础类库上造轮子么？能拿来用的就拿来用，学了框架的作用是确保自己可以满足一些爬虫需求，这是最基本的温饱问题。倘若你一直在造轮子，到最后都没造出什么来，别人找你写个爬虫研究了这么长时间了都写不出来，岂不是有点得不偿失？所以，进阶爬虫我还是建议学习一下框架，作为自己的几把武器。至少，我们可以做到了，就像你拿了把枪上战场了，至少，你是可以打击敌人的，比你一直在磨刀好的多吧？</p>
      <h2 id="框架概述"><a href="#框架概述" class="headerlink" title="框架概述"></a>框架概述</h2>
      <p>博主接触了几个爬虫框架，其中比较好用的是 Scrapy 和PySpider。就个人而言，pyspider上手更简单，操作更加简便，因为它增加了 WEB 界面，写爬虫迅速，集成了phantomjs，可以用来抓取js渲染的页面。Scrapy自定义程度高，比 PySpider更底层一些，适合学习研究，需要学习的相关知识多，不过自己拿来研究分布式和多线程等等是非常合适的。 在这里博主会一一把自己的学习经验写出来与大家分享，希望大家可以喜欢，也希望可以给大家一些帮助。</p>
      <h2 id="PySpider"><a href="#PySpider" class="headerlink" title="PySpider"></a>PySpider</h2>
      <p><a href="https://github.com/binux/pyspider" target="_blank" rel="noopener">PySpider</a>是<a href="https://github.com/binux" target="_blank" rel="noopener">binux</a>做的一个爬虫架构的开源化实现。主要的功能需求是：</p>
      <ul>
        <li>抓取、更新调度多站点的特定的页面</li>
        <li>需要对页面进行结构化信息提取</li>
        <li>灵活可扩展，稳定可监控</li>
      </ul>
      <p>而这也是绝大多数python爬虫的需求 —— 定向抓取，结构化化解析。但是面对结构迥异的各种网站，单一的抓取模式并不一定能满足，灵活的抓取控制是必须的。为了达到这个目的，单纯的配置文件往往不够灵活，于是，通过脚本去控制抓取是最后的选择。 而去重调度，队列，抓取，异常处理，监控等功能作为框架，提供给抓取脚本，并保证灵活性。最后加上web的编辑调试环境，以及web任务监控，即成为了这套框架。 pyspider的设计基础是：<strong>以python脚本驱动的抓取环模型爬虫</strong></p>
      <ul>
        <li>通过python脚本进行结构化信息的提取，follow链接调度抓取控制，实现最大的灵活性</li>
        <li>通过web化的脚本编写、调试环境。web展现调度状态</li>
        <li>抓取环模型成熟稳定，模块间相互独立，通过消息队列连接，从单进程到多机分布式灵活拓展</li>
      </ul>
      <p><img src="http://blog.binux.me/assets/image/pyspider-arch.png" alt="pyspider-arch"></p>
      <p>pyspider的架构主要分为 scheduler（调度器）, fetcher（抓取器）, processor（脚本执行）：</p>
      <ul>
        <li>各个组件间使用消息队列连接，除了scheduler是单点的，fetcher 和 processor 都是可以多实例分布式部署的。 scheduler 负责整体的调度控制</li>
        <li>任务由 scheduler 发起调度，fetcher 抓取网页内容， processor 执行预先编写的python脚本，输出结果或产生新的提链任务（发往 scheduler），形成闭环。</li>
        <li>每个脚本可以灵活使用各种python库对页面进行解析，使用框架API控制下一步抓取动作，通过设置回调控制解析动作。</li>
      </ul>
      <h2 id="Scrapy"><a href="#Scrapy" class="headerlink" title="Scrapy"></a>Scrapy</h2>
      <blockquote>
        <p>Scrapy是一个为了爬取网站数据，提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘，信息处理或存储历史数据等一系列的程序中。 其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的， 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。Scrapy用途广泛，可以用于数据挖掘、监测和自动化测试</p>
      </blockquote>
      <p>Scrapy 使用了 Twisted 异步网络库来处理网络通讯。整体架构大致如下</p>
      <p><img src="http://newtonblogimg.qiniudn.com/Scrapy%20Architecture.png" alt="Scrapy"></p>
      <p>Scrapy主要包括了以下组件：</p>
      <ul>
        <li>引擎(Scrapy): 用来处理整个系统的数据流处理, 触发事务(框架核心)</li>
        <li>调度器(Scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL（抓取网页的网址或者说是链接）的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址</li>
        <li>下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)</li>
        <li>爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面</li>
        <li>项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体，主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后，将被发送到项目管道，并经过几个特定的次序处理数据。</li>
        <li>下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架，主要是处理Scrapy引擎与下载器之间的请求及响应。</li>
        <li>爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架，主要工作是处理蜘蛛的响应输入和请求输出。</li>
        <li>调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件，从Scrapy引擎发送到调度的请求和响应。</li>
      </ul>
      <p>Scrapy运行流程大概如下：</p>
      <ul>
        <li>首先，引擎从调度器中取出一个链接(URL)用于接下来的抓取</li>
        <li>引擎把URL封装成一个请求(Request)传给下载器，下载器把资源下载下来，并封装成应答包(Response)</li>
        <li>然后，爬虫解析Response</li>
        <li>若是解析出实体（Item）,则交给实体管道进行进一步的处理。</li>
        <li>若是解析出的是链接（URL）,则把URL交给Scheduler等待抓取</li>
      </ul>
      <h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2>
      <p>对这两个框架进行基本的介绍之后，接下来我会介绍这两个框架的安装以及框架的使用方法，希望对大家有帮助。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-11 20:29:29" itemprop="dateCreated datePublished" datetime="2016-02-11T20:29:29+08:00">2016-02-11</time>
    </span>
    <span id="/2433.html" class="post-meta-item leancloud_visitors" data-flag-title="Python爬虫进阶一之爬虫框架概述" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>2.6k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2416.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> 个人随笔 <i class="label-arrow"></i>
      </a>
      <a href="/2416.html" class="post-title-link" itemprop="url">弃用多说，改用畅言</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>最近博客的多说评论总是抽风，先来吐槽一下。 刚在整理评论的时候吓我一跳，之前我的好多评论都没了，是的，是只有我自己的评论没有了，而其它人的评论还有。摸不着头脑的我打开多说后台管理，哦天，我之前所有的评论和回复全部自动转为垃圾评论了，八百多条啊，废了一会功夫好不容易批量还原了。结果刷新页面一看，咦，还是没有，重新刷一下后台，竟然再次把我的评论设成垃圾评论了，后来又退出重新绑定了其它平台的账号，总算还原回来了。 然后我就继续开始回复大家的评论呀，结果要发布评论的时候，点一下发布，按钮就卡在正在发布这里不动了。打开浏览器看一下 Ajax 出了什么问题，结果出现了一个 create_json 报了个500服务器错误，查看页面信息显示参数配置不正确还是怎么了，没错，是显示我的站点多说评论配置不正确。那，其它人怎么评论上来的？ 另外，之前，多说崩溃了已经不知道多少次了。 真是不爽的多说。 另外，多说还有一个非常令人发指的行为，会自动同步用户文章，收集用户信息，同步我们社交账号，即使是修改用户信息也要进行备份，这尼玛发展一定程度，多说还真有可能有利用这些用户信息谋利，甚至可能利用各个用户的文章做一个个性化阅读推荐也说不定。当然最开始的时候我只是觉得多说比较火，当时用上了也感觉比较方便，加上最初网站没几个东西，心想同步就同步呗，然后就一直用着了。现在再想想，也是可怕。 果断！弃用！弃用！弃用！ 搜索了网上比较热门的评论插件，发现了畅言。使用了 WordPress 插件。 于是用上了，不过还是有一些令我感到不是太友好的地方，简单在此提一下。 嗯，首先我是比较追求美感的，界面问题。首先我会关注有没有个性化主题定制这个功能，畅言还是有的，支持CSS自定义。不过这个功能比较蛋疼，如果你不选择已经提供的主题，而是选择自定义CSS样式的话，你需要把所有样式重写一遍，它缺省继承了默认主题。比如我如果想在浅色主题红色风格基础上修改几个样式的话，这是办不到的，除非重写所有的红色风格样式，这就鸡肋了。建议可以选择继承某个默认主题的功能，然后自定义的CSS是在这个基础上设置的功能。而且我看WAP版本并没有自定义CSS，非常建议增加这个功能。最后我还是选择了红色主题，不过自定义样式就写在了站点全局样式表里面了，以此解决。 其次，同步本地评论功能，由于换了插件，所以评论都留在了本地了。同步完成之后，我并不能在畅言后台管理看到我刚才同步的评论，但是新发的评论是可以看到的，页面也是可以正常显示的。只是不能在线管理早先的原始评论了。 另外，头像问题，其实我个人非常不能忍受一个账号没有头像的行为，简直是大逆不道。畅言有个QQ快速登录的功能，然而，登录之后竟然不能获取我的QQ头像！不知道是不是我这边的问题，如果大家正常希望可以反馈我一下。另外，QQ登录之后怎么会给我取了一个奇怪的用户名，叫什么cmcccc，有点醉。而微博的快速登录的昵称和头像都是正常的，然而每次评论的时候都会默认勾选那个同步到微博的按钮，这个可以默认取消么？ 还有，希望可以增加更多的平台的支持，比如微信、GitHub、脸书、推特等平台啦。 最后，有没有发表文章自动分享到各个平台的功能？我暂时没有发现。这点多说还是做得比较好的。 以上。 嗯，总之换上畅言之后用起来还是比较开心的，嘿嘿主要是改好了样式，看起来一阵舒爽。 昂，没错，我就是颜控！ 有时候，我会因为一个样式不合我意而执着地去修改，即使要花费几个小时。 有时候，我会因为一个应用的图标（没错，就是说的图标）太丑了而卸载掉，即使是它的功能再怎么好。 有时候，我会因为一个屏幕膜有一点点损伤而去重新买一个新的。额，其实是因为今天给电脑贴膜折角了，我又花了几十块重新买了一个新的。 有时候，我就是一个强迫症，在写上面三句话的时候，第一句原本是在第二行的，然而因为看起来长度参差不齐我就把它移动到了最上面。嗯，这第四句话要写得更长才行。 好啦，貌似跑题了，时候不早啦，大家晚安。 嗯，换上调教好的美美的畅言还是很开心的，文章前后呼应，拜～ <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/屏幕快照-2016-02-03-03.43.51.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2016/02/屏幕快照-2016-02-03-03.43.51-1024x622.png" alt="屏幕快照 2016-02-03 03.43.51"></a> 美美哒～</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-03 03:36:48" itemprop="dateCreated datePublished" datetime="2016-02-03T03:36:48+08:00">2016-02-03</time>
    </span>
    <span id="/2416.html" class="post-meta-item leancloud_visitors" data-flag-title="弃用多说，改用畅言" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>1.7k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2401.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> 个人日记 <i class="label-arrow"></i>
      </a>
      <a href="/2401.html" class="post-title-link" itemprop="url">强势回归博客，顺便祝大家小年快乐</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>Hello，时隔一个多月，终于再次回到博客啦，首先跟大家说声抱歉，许多评论没有及时回复感到非常抱歉，希望我现在给大家的回复为时不晚。 距离上次在博客上写日记过去了几个月了吧。那时的我刚刚结束大学三年级。而现在，大四上半学期已经过半啦。这半年的时间可以说忙也可以说不忙。不忙是说这半年以来的课程比较轻松，只有四门选修课，学业负担比较轻。忙是说半年以来各种错综复杂的事情，许多事情需要好好安排一下时间才可以好好把握各个“进程”的合理分配。 那么就从我上次日记开始总结一下吧。 当时更新是去年七月十二日，刚大三放假不久。那个暑假前期过得可谓是心惊胆战呀，当时为了保研北京航空航天大学一直在紧张地复习准备。包括复习备考三年的专业课，还有准备C语言的上机考试。七月二十八二十九那两天机考和面试，不负众望，我顺利拿到了北京航空航天大学计算机科学与技术学院的Offer，心里的石头也落了地，当时看到通过面试的消息时真的激动得说不出口，这也算是我人生中为数不多的重大十字路口做出的一个选择吧。 面试结束之后，我便留在了导师那边做项目，一些大数据处理和爬虫的项目。不过当时的项目个人感觉比较简单，所以就在整个八月份找了一份实习，PHP研发工程师的岗位，之前准备保研也一直没有找工作，这也算是我找的第一份工作吧，不求赚神马，只求充实一下我的假期，也学习一些新的东西。 在这里顺便安利一下，公司名称是佳信德润，主打品牌是<a href="http://www.lingxi360.com/index.php" target="_blank" rel="noopener">灵析</a>，北京三环。在那边工作真的感觉特别舒心，虽然是创业公司，但是CEO玛丽老板（女哦）还有负责技术的柱子哥真的超级热情，为人特别好，谈吐之间就有一种亲切的感觉，那边的小伙伴十几个，相处地也十分融洽。在那边工作你不会有一种被忽视和指使的感觉，你可以随意向老板们发表自己的看法，甚至你可以与他们探讨代码问题，甚至公司某处的装饰啦，哪里的餐馆不错啦等等。有次我眼睛发炎，玛丽老板和柱子哥还特别关心我，亲自送到我医院，在这里再次说声谢谢，不知道你们是不是可以看到。我还记得小伙伴们一起拍公司写真，真的超赞。当然最主要的还是一起商讨项目进度，代码问题，接触到我之前没有接触过的新知识。在这里你可以负责许多事情，最大限度地发挥你的光和热。不是我打广告，如果有小伙伴们有意向做PHP，非常推荐你们过去，可以去他们<a href="http://www.lingxi360.com/index.php" target="_blank" rel="noopener">官网</a>发应聘哦。相信我，不会坑你的。 实习时间真的过得很快，转眼一个月过去了，九月份来了，大四开学啦。 因为需要开学以后办一些保研的相关手续，另外重要的事当然是陪妹纸啦嘿嘿，你懂得。 开学之后就开始忙一些项目了。大四的课程不紧，趁着这大四的时光，多学点东西，以后这样的日子真不多了，好好珍惜。 所以大四上学期的基调是，专注陪妹子，业余撸代码，顺便做做外包。请叫我全职男朋友，兼职程序猿。 这半年以来做的项目不算多。首先，学习了Laravel框架，嗯，保证你学完之后就不想用其他的框架了。最开始是帮我的叔叔做一个拍电影的网站，规模还比较大，一直在完善中。另外在暑假实习的过程中发现了公司自己写了一款CMS框架，自己觉得还有许多功能可以添加，一些架构可以继续完善，所以决定自己写一个CMS，不仅算是练手，也算是造轮子吧。毕竟你写好了就是你自己的，用起来都是那么自然，假如来了个外包神马的，轻松应对分分钟的事，神马深度定制都是浮云。当然还有帮爸爸妈妈写的一个微信平台，在微信订餐售卖东西，嗯，这叫做自己动手实现O2O。另外就是一些零零散散的小外包，没事可以赚点外快养活一下自己。 最近刚刚入手了自己人生中的第一台MAC，当然还是要感谢父亲大人的支持，自己的手头还是比较紧的，你懂得。 嗯摒弃Windows，感觉撸代码的快感不止提升了几管气，也希望它可以陪我度过接下来许多年的学习时光。在这里也安利一下一个小店，微博上的<a href="http://weibo.com/u/2067562447?is_hot=1" target="_blank" rel="noopener">小闷小闷</a>，水果从她这里买，价格真的是十分公道啊，正品无误了，入手十几天了，感觉逼格提升了，心情也舒畅了，多年的Windows卡顿症也治好了～ 嗯，接下来的时间，爸爸妈妈年前工作辛苦，接下来几天我要去帮他们分担一下工作啦。 最后，恭祝大家小年快乐，工作顺心，别跟钱过不去，开心最重要～ 欢欢喜喜过大年啦～</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-02-01 20:20:53" itemprop="dateCreated datePublished" datetime="2016-02-01T20:20:53+08:00">2016-02-01</time>
    </span>
    <span id="/2401.html" class="post-meta-item leancloud_visitors" data-flag-title="强势回归博客，顺便祝大家小年快乐" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>1.7k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2353.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> HTML <i class="label-arrow"></i>
      </a>
      <a href="/2353.html" class="post-title-link" itemprop="url">关于HTML内联元素一侧留白的浅谈</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="问题来源"><a href="#问题来源" class="headerlink" title="问题来源"></a>问题来源</h2>
      <p>在写代码的时候遇到了如下问题： 使用了bootstrap框架来编写了一个页面，其中input元素两侧留有空白。然而用JS动态添加的同样的元素却不会出现这种情况。具体截图表现如下： <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226212230.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226212230.png" alt="20151226212230"></a> 我们可以发现，第一行和而三行的代码是完全一样的，可是呈现的结果是截然不同的。 <a href="http://res.cuiqingcai.com/demo/inline.html" target="_blank" rel="noopener">在线测试样例</a> 大家是不是觉得很奇怪？没错，我也是。中间的那个缝隙是哪里来的呢？</p>
      <h2 id="刨根问底"><a href="#刨根问底" class="headerlink" title="刨根问底"></a>刨根问底</h2>
      <p>在这里感谢 <a href="http://wonderlee.me" target="_blank" rel="noopener">wonder</a> 同学的大力相助，才得以找到问题的所在。 出现此问题的原因在于：</p>
      <blockquote>
        <p>html中的内联元素在书写代码时，如果两元素代码之间有换行，浏览器会将其解释为空格。而这个空格是会被当作一个空白节点（nodeType等于3的节点，就是文字节点）</p>
      </blockquote>
      <p>所以，因为代码中我使元素呈现 inline 的属性，然后两个代码之间具有换行，所以二者之间出现了空白。正常情况下，二者之间是不应该出现空白的。然而用 jQuery 生成元素的时候，因为是用的 + 连接符，所以换行符被忽略了。也就是代码是连接起来的，所以二者之间便不会出现空白。 解决方法： 1.将原代码中的input写到一行。如下：</p>
      <figure class="highlight pgsql">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">&lt;div <span class="keyword">class</span>="form-group"&gt;</span><br><span class="line">    &lt;<span class="keyword">input</span> <span class="keyword">class</span>="form-control inline span3" <span class="type">name</span>="education[school][]" <span class="keyword">type</span>="text" <span class="keyword">value</span>="123"&gt;&lt;<span class="keyword">input</span> <span class="keyword">class</span>="form-control inline span3" <span class="type">name</span>="education[date][]" <span class="keyword">type</span>="text" <span class="keyword">value</span>="456"&gt;</span><br><span class="line">&lt;/div&gt;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>2.或者在JS代码中加入换行符。如下：</p>
      <figure class="highlight scala">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">$(<span class="symbol">'butto</span>n').on(<span class="symbol">'clic</span>k', function() &#123;</span><br><span class="line">        $('&lt;div <span class="class"><span class="keyword">class</span></span>=<span class="string">"form-group"</span>&gt;'+</span><br><span class="line">            '&lt;input <span class="class"><span class="keyword">class</span></span>=<span class="string">"form-control inline span3"</span> name=<span class="string">"education[school][]"</span> <span class="class"><span class="keyword">type</span></span>=<span class="string">"text"</span> value=<span class="string">""</span>&gt;\n'+</span><br><span class="line">            '&lt;input <span class="class"><span class="keyword">class</span></span>=<span class="string">"form-control inline span3"</span> name=<span class="string">"education[date][]"</span> <span class="class"><span class="keyword">type</span></span>=<span class="string">"text"</span> value=<span class="string">""</span>&gt;'+</span><br><span class="line">        '&lt;/div&gt;').appendTo($(<span class="string">".content"</span>));</span><br><span class="line">    &#125;);</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>以上两种方式，解决方法都比较简单实用。其他的改变 padding 或者 margin 的方法就不推荐了。 好了，那么明白了之后，我们肯定要可以举一反三的，来探究一下如果是块级元素会不会这样呢？</p>
      <h2 id="举一反三"><a href="#举一反三" class="headerlink" title="举一反三"></a>举一反三</h2>
      <p>好的，让我们试一下块级元素如果设置为 inline的话会不会也这样。 把 input 标签改成 div，然后给它加上 display: inline 属性，加一下背景颜色区分，观察一下效果。 代码如下：</p>
      <figure class="highlight xml">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"zh-CN"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"X-UA-Compatible"</span> <span class="attr">content</span>=<span class="string">"IE=edge"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>点击按钮添加元素<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"content"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"form-group"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"item"</span>&gt;</span>hello1<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"item"</span>&gt;</span>hello2<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"btn btn-primary"</span>&gt;</span>添加<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css">    <span class="selector-class">.item</span> &#123;</span></span><br><span class="line">        display: inline;</span><br><span class="line"><span class="css">        <span class="selector-tag">background</span>: <span class="selector-id">#555</span>;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>观察一下效果 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220135.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220135.png" alt="20151226220135"></a> 嗯，果然，它的间距还是出现了。 那么改成 display: inline-block 呢？</p>
      <figure class="highlight css">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="selector-class">.item</span> &#123;</span><br><span class="line">        <span class="attribute">display</span>: inline-block;</span><br><span class="line">        <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">        <span class="attribute">background</span>: <span class="number">#555</span>;</span><br><span class="line">    &#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p><a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220326.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220326.png" alt="20151226220326"></a> 可见间距还是有的。 我们把 div 的换行去掉，看一下。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220443.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151226220443.png" alt="20151226220443"></a> Perfect！它已经消失不见了！ 以上，在chrome，edge，ie11测试通过。</p>
      <h2 id="综述"><a href="#综述" class="headerlink" title="综述"></a>综述</h2>
      <p>通过以上研究我们可以得出如下结论： 内联元素，代码中带有换行，会出现空白间距。块级元素，设置了内联样式，且代码中带有换行，也会出现空白间距。 解决方法是删除代码中的换行即可。 以上是在写程序过程中发现的现象，希望能对大家有帮助！</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2016-01-02 22:08:42" itemprop="dateCreated datePublished" datetime="2016-01-02T22:08:42+08:00">2016-01-02</time>
    </span>
    <span id="/2353.html" class="post-meta-item leancloud_visitors" data-flag-title="关于HTML内联元素一侧留白的浅谈" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>2.4k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/455.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Other <i class="label-arrow"></i>
      </a>
      <a href="/455.html" class="post-title-link" itemprop="url">干货！IT小伙伴们实用的网站及工具大集合！持续更新！</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>1.Git 还在担心自己辛辛苦苦写的代码被误删了吗？还在担心自己改错了代码不能挽回吗？还在苦恼于多人开发合作找不到一个好的工具吗？那么用Git就对了，Git是一个开源的分布式版本控制系统，用以有效、高速的处理从很小到非常大的项目版本管理。有了它，代码托管不是问题，版本控制不再苦恼，多人开发变得简单易行。 链接：<a href="http://git-scm.com/" target="_blank" rel="noopener">http://git-scm.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124142208-e1416810150194.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124142208-1024x341.jpg" alt="QQ截图20141124142208"></a> 2.GitHub 学会了Git之后，我们把代码托管到哪里呢？在此推荐给大家两个网站，GitHub，一个是国外免费的代码托管平台。许许多多的开源项目几乎都托管在上面，你也可以在上面搜一些你需要的源代码，丰富资源应有尽有，如果还不知道这个，是不是已经Out了呢？ 链接：<a href="https://github.com/" target="_blank" rel="noopener">https://github.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124142704-e1416810453291.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124142704-1024x415.jpg" alt="QQ截图20141124142704"></a> 3.GitCafe 和GitHub一样，也是一个免费的代码托管平台。GitHub是国外的，GitCafe是国内的。两者功能几乎相同，不喜欢英文版的朋友可以来GitCafe尝尝鲜。 链接：<a href="http://gitcafe.com/" target="_blank" rel="noopener">http://gitcafe.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124143049-e1416810670667.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124143049-1024x484.jpg" alt="QQ截图20141124143049"></a> 4.七牛云存储 还在为自己项目的图片等资源没处存放而着急吗？还在担心图片加载耗费你主机大量流量吗？还在为你自己的网站加载速度过慢而揪心吗？云时代，就要用云存储。 比如我有一个虚拟主机是每月限流量的，而大量的图片加载占据了我网站访问流量的大部分，这时我们就可以考虑将图片移植到七牛云存储上，图片通过七牛来加载，节省宝贵的主机空间和流量。比如我的个人网站已经移植到了七牛，所有网页图片的加载都是从七牛上获取，速度快而且省流量。而且免费的七牛还提供了图片处理，比如压缩，水印等各种图片加工方式，想要什么有什么。 链接：<a href="http://www.qiniu.com/" target="_blank" rel="noopener">http://www.qiniu.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124143837-e1416811137547.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124143837-1024x432.jpg" alt="QQ截图20141124143837"></a> 5.云适配 有时候我们做出的网站没有用到响应式布局，也可能我们的网站DIV的像素宽度已经规定成具体的多少像素了。所以，用手机访问的时候可能就会出现这样那样的问题，或者显示得很小，或者整个布局全都乱掉了。这时，我们需要把自己的网站适配一下，那么在此推荐一个网站，云适配。插入一行代码，通过在线修改和生成手机适配效果，得到手机访问的网页最佳适配效果，方便而又快捷。这时电脑和手机均能看到最佳适配效果了。 链接：<a href="http://www.yunshipei.com/" target="_blank" rel="noopener">http://www.yunshipei.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124144434-e1416811549465.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124144434-1024x404.jpg" alt="QQ截图20141124144434"></a> 6.聚合数据 大家在开发过程中，可能会用到各种各样的数据，想找一些接口来提供一些数据。比如天气预报查询，火车时刻表查询，彩票查询，身份证查询等等。有了这个接口，直接调用即可。各种各样的API接口满足你。 链接：<a href="http://www.juhe.cn/" target="_blank" rel="noopener">http://www.juhe.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124150336-e1416812634424.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124150336-1024x439.jpg" alt="QQ截图20141124150336"></a> 7.够快云库 够快云库，是基于云存储的团队协作性文件管理平台。 团队成员可以同步共享资料，即时沟通交流，便捷移动办公，从而实现团队的100％高效运作。比如团队开发过程中有什么要共享的资料，就可以放到里面。支持在线编辑和修改，小组讨论合作等方式。 链接：<a href="http://www.gokuai.com/" target="_blank" rel="noopener">http://www.gokuai.com/</a><a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124150727-e1416812868208.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124150727-1024x370.jpg" alt="QQ截图20141124150727"></a> 8.SAE SAE的强大不用多说了，强大的虚拟主机提供商。提供各种各样的编程语言在线运行，同时提供云存储Storage，各种数据库，应用十分广泛。不仅提供代码托管，还提供在线服务器运行，JAVA，PHP，Python等等的支持应有尽有，在这里你可以假设你自己的网站，你的应用接口，你的创意应用。好不好，用用就知道。另外还有JAE（京东），BAE（百度），功能类似，也推荐一下。 链接：<a href="http://sae.sina.com.cn/" target="_blank" rel="noopener">http://sae.sina.com.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124151607-e1416813413924.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124151607-1024x360.jpg" alt="QQ截图20141124151607"></a> 9.多备份 多备份提供了主机的文件备份及数据库的备份。可能对于文件的备份大家都已经有其他方法了，不过数据库的自动备份现在还没有多少有效的解决方法，人工备份又显得比较麻烦。如果数据库有数据丢失，那就不好找回了。在此推荐一个网站：多备份。提供主机的文件自动备份和数据库自动备份，方便快捷。 链接：<a href="http://www.dbfen.com/" target="_blank" rel="noopener">http://www.dbfen.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152121-e1416813698270.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152121-1024x410.jpg" alt="QQ截图20141124152121"></a> 10.慕课网 学习IT知识哪家强？在此为大家推荐一个全免费的学习网站，资源丰富，还提供了比较创新的学习和练习相结合的方式。感觉非常不错，讲解得也很有条理，推荐一下。 链接：<a href="http://www.imooc.com/" target="_blank" rel="noopener">http://www.imooc.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152408-e1416813887400.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152408-1024x410.jpg" alt="QQ截图20141124152408"></a> 11.W3SCHOOL 这也是一个非常棒的学习网站，讲解简单易懂，我的PHP入门，HTML，JS，CSS入门都是从这里学到的，感觉讲解非常不错。 链接：<a href="http://www.w3school.com.cn/" target="_blank" rel="noopener">http://www.w3school.com.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152659-e1416814040907.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124152659-1024x393.jpg" alt="QQ截图20141124152659"></a> 12.阿里云 感觉比较不错的主机提供商，提供免费备案，对于ECS的管理做得非常好，数据恢复和备份及监控也应有尽有，另外提供了SLB，RDS，CDN等等的支持，个人感觉很不错的主机提供商。就是价格略贵！ 链接：<a href="http://www.aliyun.com/" target="_blank" rel="noopener">http://www.aliyun.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124153235.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124153235-1024x322.jpg" alt="QQ截图20141124153235"></a> 13.DNSPod 免费的域名解析提供商，管理方便，简洁高效。非常人性化的提示，还提供域名D监控等功能，方便实用。 链接：<a href="https://www.dnspod.cn/" target="_blank" rel="noopener">https://www.dnspod.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124153637-e1416814632344.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124153637.jpg" alt="QQ截图20141124153637"></a> 14.WordPress 一款开源的PHP框架，搭建个人博客网站最实用的选择之一。我的个人网站就是基于此搭建，甚至你都不需要懂PHP你就可以搭建自己的个人网站。提供强大的后台文章管理和插件及主题管理，几乎可以满足个人网站所有需求。 P.S.找个好的网站模板，你就相当于成功了一大半。 链接：<a href="http://cn.wordpress.org/" target="_blank" rel="noopener">http://cn.wordpress.org/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154227-e1416814969553.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154227.jpg" alt="QQ截图20141124154227"></a> 15.BootStrap 一个强大的前端框架，有了它你再也不需要敲那么多行的样式表，再也不用一点点地调试难看的DIV了。直接调用各种CSS样式，分分钟写出好看的网页界面。按钮、表格、进度条、提示框、输入框、菜单，应有尽有。 链接：<a href="http://www.bootcss.com/" target="_blank" rel="noopener">http://www.bootcss.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154554.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154554-1024x428.jpg" alt="QQ截图20141124154554"></a> 16.芒果广告 如果你开发了自己的移动应用，想添加广告来赚钱，推荐芒果广告。它是一个综合的移动广告平台，聚合了百度广告、多盟广告、易传媒等等广大广告商，可以自己定制广告显示的内容及样式，可以选择各种广告的投放比例。广告点击量、展现量详细报告、收入分析详细数据应有尽有。推荐一下。 链接：<a href="http://www.adsmogo.com/" target="_blank" rel="noopener">http://www.adsmogo.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154953.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124154953-1024x488.jpg" alt="QQ截图20141124154953"></a> 17.极光推送 极光推送，使得开发者可以即时地向其应用程序的用户推送通知或者消息，与用户保持互动，从而有效地提高留存率，提升用户体验</p>
      <p>平台提供整合了Android推送、iOS推送的统一推送服务。让用户可以更好地接收你推送的内容。 链接：<a href="https://www.jpush.cn/" target="_blank" rel="noopener">https://www.jpush.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124155237.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124155237-1024x434.jpg" alt="QQ截图20141124155237"></a> 18.Bmob 提供强大的后台接口支持，移动开发过程中可能需要各种各样的后台接口，直接利用这个，你可以创建自己的后台接口。它还提供了强大的游戏后端支持数据，文档和教程也是非常的完备，为移动开发带来相当大的便利。 链接：<a href="http://www.bmob.cn/" target="_blank" rel="noopener">http://www.bmob.cn/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124155600.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124155600-1024x560.jpg" alt="QQ截图20141124155600"></a></p>
      <p>19.有道云笔记 大多数人都听说过吧？在学习或者开发过程中可能会有各种各样的知识点，好记性不如烂笔头。最好的方式就是记录下来。在此推荐一个笔记，有道云笔记。在使用了各种笔记工具之后，发现还是有道好用。它提供了个人云笔记，云协作等功能，做到PC、手机、平板等多处同步。占用小，界面美观，使用方便。 链接：<a href="http://note.youdao.com/" target="_blank" rel="noopener">http://note.youdao.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124160008.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124160008-1024x496.jpg" alt="QQ截图20141124160008"></a> 20.Coding 集合了GitHub和SAE的功能，利用Git上传代码，并对代码进行托管，而且提供了一键部署和运行的功能。提供了代码监控功能，通过自动化静态代码分析等管理工具，发现代码问题，获取代码度量信息，及时了解代码质量状况。一个新兴网站，推荐一下！ 链接：<a href="https://coding.net" target="_blank" rel="noopener">https://coding.net</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161059.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161059-1024x349.jpg" alt="QQ截图20141124161059"></a> 21.SendCloud 开发过程中你可能会遇到邮件发送的功能，用了SendCloud，一切都方便多了，它提供免费的邮件代发功能。邮件发送的难题，就交给它来解决吧。 链接：<a href="http://sendcloud.sohu.com/" target="_blank" rel="noopener">http://sendcloud.sohu.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161409.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161409-1024x403.jpg" alt="QQ截图20141124161409"></a> 22.蒲公英 有时候你发布Android市场，发布Appstore，会花费相当多的时间才能得到审核通过。那么在团队之间，想团队之间提供内测功能，那么就可以用到它啦，这里提供了一个发布应用的平台，发布之后，生成链接和二维码，即可实现下载测试，简单方便。 链接：<a href="http://www.pgyer.com/" target="_blank" rel="noopener">http://www.pgyer.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161757.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124161757-1024x396.jpg" alt="QQ截图20141124161757"></a> 23.DCloud HTML5现在已经定稿，用HTML5开发APP的浪潮即将袭来，在此提供一个免费的开发网站。它提供了一个HBuilder的工具，以及H5APP开发文档及H5APP的开发框架MUI框架，有了它，H5APP的开发变得相当简单，而我也在蠢蠢欲动。 链接：<a href="http://www.dcloud.io/" target="_blank" rel="noopener">http://www.dcloud.io/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162042.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162042-1024x485.jpg" alt="QQ截图20141124162042"></a> 24.青云 提供免费的云服务器、云存储、云数据库的功能。同时提供多个开放API，功能实用，非常强大。 链接：<a href="https://www.qingcloud.com/" target="_blank" rel="noopener">https://www.qingcloud.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162338.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162338-1024x425.jpg" alt="QQ截图20141124162338"></a> 25.云测 开发了应用之后到哪里去测试？选择云测没错。它提供应用云测试、手机游戏测试，提供崩溃分析。一切测试由它来搞定。 链接：<a href="http://www.testin.cn" target="_blank" rel="noopener">http://www.testin.cn</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162721.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2014/11/QQ截图20141124162721-1024x403.jpg" alt="QQ截图20141124162721"></a> 26.Meteor Meteor 是一个构建在 Node.js 之上的平台，用来开发实时网页程序。Meteor 位于程序数据库和用户界面之间，保持二者之间的数据同步更新。 链接：<a href="https://www.meteor.com/" target="_blank" rel="noopener">https://www.meteor.com/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/屏幕快照-2016-02-21-14.04.17.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/屏幕快照-2016-02-21-14.04.17-1024x462.png" alt="屏幕快照 2016-02-21 14.04.17"></a> 暂时先分享给大家这么多！如果有好的网站或者应用推荐，欢迎与我交流，可以评论，可以留言！以上是一些比较实用的网站和工具的分享！希望能给大家的生活和开发带来一定的便利！Thanks！</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-12-24 16:32:36" itemprop="dateCreated datePublished" datetime="2015-12-24T16:32:36+08:00">2015-12-24</time>
    </span>
    <span id="/455.html" class="post-meta-item leancloud_visitors" data-flag-title="干货！IT小伙伴们实用的网站及工具大集合！持续更新！" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>3.8k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>3 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2322.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Other <i class="label-arrow"></i>
      </a>
      <a href="/2322.html" class="post-title-link" itemprop="url">使用PGP加密你的文件</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2>
      <p>有时候，一些文件是不想公开让被人看到的，或者只想某些特定的人看到。 比如说，你要上交一个实验报告啦，老师给了一个FTP上传目录，但是你只想让老师看到报告，而不想公开给同学们看。这时候，就需要加密一下你的文件啦。 那么有什么好的加密方式呢？PGP，你的不二之选。</p>
      <h2 id="PGP加密原理"><a href="#PGP加密原理" class="headerlink" title="PGP加密原理"></a>PGP加密原理</h2>
      <p>用直白的话来讲就是 对方给你一个公钥，他自己也保存了一个私钥，你利用他的公钥来加密，只有对方自己用自己私钥才能解密。由于其他的人没有拿到私钥，所以解不开的，即使是你自己，也解不开的。所以，这样就保证了，只有你和对方可以查看内容。 引用详解原理：</p>
      <blockquote>
        <p>PGP(Pretty Good Privacy)，是一个基于RSA公钥加密体系的邮件加密软件。可以用它对邮件保密以防止非授权者阅读，它还能对邮件加上数字签名从而使收信人可以确认邮件的发送者，并能确信邮件没有被篡改。它可以提供一种安全的通讯方式，而事先并不需要任何保密的渠道用来传递密匙。它采用了一种RSA和传统加密的杂合算法，用于数字签名的邮件文摘算法，加密前压缩等，还有一个良好的人机工程设计。它的功能强大，有很快的速度。 PGP是一种供大众使用的加密软件。电子邮件通过开放的网络传输，网络上的其他人都可以监听或者截取邮件，来获得邮件的内容，因而邮件的安全问题就比较突出了。保护信息不被第三者获得，这就需要加密技术。还有一个问题就是信息认证，如何让收信人确信邮件没有被第三者篡改，这就需要数字签名技术。RSA公钥体系的特点使它非常适合用来满足上述两个要求：保密性（Privacy)和认证性（Authentication）。 RSA（Rivest-Shamir-Adleman）算法是一种基于大数不可能质因数分解假设的公匙体系。简单地说就是找两个很大的质数，一个公开即公钥，另一个不告诉任何人，即私钥。这两个密匙是互补的，就是说用公匙加密的密文可以用私匙解密，反过来也一样。 假设甲要寄信给乙，他们互相知道对方的公匙。甲就用乙的公匙加密邮件寄出，乙收到后就可以用自己的私匙解密出甲的原文。由于没别人知道乙的私匙，所以即使是甲本人也无法解密那封信，这就解决了信件保密的问题。另一方面由于每个人都知道乙的公匙，他们都可以给乙发信，那么乙就无法确信是不是甲的来信。这时候就需要用数字签名来认证。</p>
      </blockquote>
      <h2 id="加密流程"><a href="#加密流程" class="headerlink" title="加密流程"></a>加密流程</h2>
      <p>在 Windows 下，有一个非常强大的工具，叫做 PGP Desktop，可以利用这个来加密。 <a href="http://pan.baidu.com/s/1dEznwe1" target="_blank" rel="noopener">下载链接</a> 这个是 64 位的安装包，安装过程我就不详细描述了，比较简单。如果你的系统是 32 位，那么请再寻找一下其他的安装包。 安装之后，搜索一下开始菜单或者安装目录，找到 PGP Desktop，打开它。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003158.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003158.png" alt="20151215003158"></a> 打开之后界面是这个样子的 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003312.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003312-1024x664.png" alt="20151215003312"></a> 恩，别人应该给了你公钥了对吧，比如，这次老师的公钥是</p>
      <figure class="highlight excel">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">-----BEGIN PGP PUBLIC KEY BLOCK-----</span><br><span class="line">Versi<span class="symbol">on:</span> PGPfreeware <span class="number">6.5</span>.<span class="number">8</span> for non-commercial use &lt;ht<span class="symbol">tp:</span>//www.pgp.com&gt;</span><br><span class="line"></span><br><span class="line">mQCNA1NKJuwAAAEEAMvdBmw1TTTkLTL6w9C28MhtVnsWtNeHVJl98CFCzOveyKDH</span><br><span class="line">KGPf/RA4moDUE1IkkUelRKJV1O2JlcqBZPOGI/FII/<span class="number">6</span>yq/DbNHKOKhz6fgbbdgxh</span><br><span class="line">UArjUSthA/BPnodTcEtGZHlGSvK7n3TcWmGY700YB9crWpbyHfVQ7KLGc3SlAAUR</span><br><span class="line">tCF0ZXN0NGNyeXB0byA8dGVzdDRjcnlwdG9AMTYzLmNvbT6JAJUDBRBTSibs9VDs</span><br><span class="line">osZzdKUBAQzxBACr3UpakH7SMtU9OgHHZCARE4xKVChTBCh9kquhhU5Kr9Er0AHy</span><br><span class="line">UWO1BD+z58VTu9XPR2/NSrCOGNwfZVqZTY8eTUTuQVJKpAR9CNtRi0B6yQa8pQVm</span><br><span class="line"><span class="number">7</span>vfEqzBcsWcPkOzfRU75Ubdc+IxZkdMcPfPnzn1kU2cTKUIlM5+cy/+qvw==</span><br><span class="line">=nNyG</span><br><span class="line">-----END PGP PUBLIC KEY BLOCK-----</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>来，添加一下，有一个非常简单的方法就是直接右键粘贴，然后确定就好了。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003737.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003737.png" alt="20151215003737"></a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003953.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215003953.png" alt="20151215003953"></a> 然后，你可以把这个公钥加到你的 Master Keys 里。 点击，菜单中的 Tools -&gt; PGP Options -&gt; Master Keys -&gt; Add -&gt; add -&gt; OK，按照图示箭头操作即可。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011210.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011210-1024x596.png" alt="20151215011210"></a> 然后，确定，邮件点一下 添加到 Master Keys。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011305.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011305.png" alt="20151215011305"></a> 会提示成功添加。然后接下来就进行加密吧。 点左侧的 PGP ZIP，然后 New PGP Zip，然后选择文件，点击确定。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215004710.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215004710.png" alt="20151215004710"></a> 然后直接下一步 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215004802.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215004802.png" alt="20151215004802"></a> 直接下一步 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011736.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011736.png" alt="20151215011736"></a> 然后下一步，选择导出路径即可 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011755.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151215011755.png" alt="20151215011755"></a> 下一步，导出成功，加密完成。 导出的文件格式就是原文件名加了 pgp 后缀，只有对方的私钥可以解开。 当然如果有不死心的小伙伴想破解，自己试试咯~</p>
      <h2 id="综述"><a href="#综述" class="headerlink" title="综述"></a>综述</h2>
      <p>以上，为了便于演示，我直接将秘钥添加到了 Master Key 中，其实这个 Master Key 当然最好是你自己专属的秘钥咯，不过无所谓啦，我们只是为了演示一下加密过程，利用这个公钥加密，不要在意这些细节。 小伙伴们体验一下吧！</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-12-15 01:23:40" itemprop="dateCreated datePublished" datetime="2015-12-15T01:23:40+08:00">2015-12-15</time>
    </span>
    <span id="/2322.html" class="post-meta-item leancloud_visitors" data-flag-title="使用PGP加密你的文件" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>2.1k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2286.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Other <i class="label-arrow"></i>
      </a>
      <a href="/2286.html" class="post-title-link" itemprop="url">计算机网络探究四之使用FreeNAS提供网络硬盘</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="FreeNAS简介"><a href="#FreeNAS简介" class="headerlink" title="FreeNAS简介"></a>FreeNAS简介</h2>
      <p>FreeNAS 是什么？ FreeNAS 是一款广受赞誉的开源免费 NAS 操作系统。它能把普通台式机瞬间变成一台多功能 NAS 服务器。不但适用于企业文件共享，同样适用于打造家庭媒体中心。 FreeNAS 支持多种共享协议，包括 SMB/CIFS、NFS、AFP、WebDAV、iSCSI、FTP/TFTP、RSync等。 <a href="http://www.getnas.com/" target="_blank" rel="noopener">官方网站</a></p>
      <h2 id="iSCSI"><a href="#iSCSI" class="headerlink" title="iSCSI"></a>iSCSI</h2>
      <p>iSCSI技术是一种由IBM公司研究开发的，是一个供硬件设备使用的可以在IP协议的上层运行的SCSI指令集，这种指令集合可以实现在IP网络上运行SCSI协议，使其能够在诸如高速千兆以太网上进行路由选择。iSCSI技术是一种新储存技术，该技术是将现有SCSI接口与以太网络(Ethernet)技术结合，使服务器可与使用IP网络的储存装置互相交换资料。 iSCSI：Internet 小型计算机系统接口 （iSCSI：Internet Small Computer System Interface）。</p>
      <h2 id="本篇目标"><a href="#本篇目标" class="headerlink" title="本篇目标"></a>本篇目标</h2>
      <p>那么本篇文章的目标就是记录一下怎样使用 FreeNAS 配置一个输入我们的网络存储服务。</p>
      <h2 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h2>
      <p>首先我们要下载 FreeNAS的镜像，由于FreeNAS 9 对系统的要求比较高，在这里我们用到的是 FreeNAS 8。 <a href="http://pan.baidu.com/s/1geb2C1t" target="_blank" rel="noopener">镜像下载</a> 下载完成之后我们利用 VMware安装即可。 安装界面提供了四个选项：</p>
      <ol>
        <li>Install/Upgrade 安装/升级</li>
        <li>Shell 终端</li>
        <li>Reboot System 重启系统</li>
        <li>Shutdown System 关闭系统</li>
      </ol>
      <p><img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129171248.png" alt="20150129171248"> 使用键盘上的方向键切换菜单，选择第一项，按回车键确认。 接下来系统会提示选择 FreeNAS 系统盘，在如下图所示的界面中会显示出所有可以用作安装 FreeNAS 系统的设备。你需要根据自己界面上显示的实际内容进行选择，此处应该选择我们准备作为 FreeNAS 系统盘的另一块U盘，选择好以后按回车键确认。 <img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129171601.png" alt="20150129171601"> 此时，界面上显示了一些警告信息，大意为“你选择作为 FreeNAS 系统盘的设备上的所有数据都会被清空，而且该设备将完全被系统占用，不能用作数据存储。” 按回车键确认。 <img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129171850.png" alt="20150129171850"> 确认后，系统开始执行安装，如下图所示。 <img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129172137.png" alt="20150129172137"> 系统安装完成后会给出成功提示，提醒我们移除安装盘，如下图。不用理会，按回车键继续。 <img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129172300.png" alt="20150129172300"> 此时，系统又回到了最初的安装界面，如下图所示。用方向键切换选择第四项，按回车键关闭系统。 <img src="http://7xnt0e.com1.z0.glb.clouddn.com/wp-content/uploads/2015/01/20150129172526.png" alt="20150129172526"> 待系统完全关闭以后，再次启动电脑，并设置从 U盘系统盘引导，成功启动以后，看到如下所示的界面，代表系统已经安装完成。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171035.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171035.png" alt="20151213171035"></a> 接下来，你可以使用浏览器访问界面中给出的 IP 地址打开 FreeNAS 的 WebGUI 管理界面了。</p>
      <h2 id="网页配置"><a href="#网页配置" class="headerlink" title="网页配置"></a>网页配置</h2>
      <p>接下来，我们就可以通过浏览器来配置我们的 FreeNAS了。 通过系统的提示，我们访问以下链接即可： <a href="http://192.168.231.131/" target="_blank" rel="noopener">http://192.168.231.131/</a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171159.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171159-1024x549.png" alt="20151213171159"></a> 访问之后，可以看到如上内容。 点击 setting，先切换一下语言，简体中文。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171352.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171352.png" alt="20151213171352"></a> 接下来我们便开始iSCSI的配置啦。</p>
      <h2 id="iSCSI配置"><a href="#iSCSI配置" class="headerlink" title="iSCSI配置"></a>iSCSI配置</h2>
      <p>1.首先开启iSCSI服务，然后点击右侧的设置图标进入设置界面。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213173030.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213173030.png" alt="20151213173030"></a> 2.添加iSCSI端口，选择默认设置即可。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171558.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171558.png" alt="20151213171558"></a> 3.添加网络授权信息 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171648.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171648.png" alt="20151213171648"></a> 两个全部填写为ALL即可。 4.添加iSCSI用户信息 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171733.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171733.png" alt="20151213171733"></a> 填入用户信息和秘钥即可，下方的输入框是加密可选的。 5.添加iSCSI属性信息 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171855.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171855.png" alt="20151213171855"></a> 6.添加存储设备 在这里我们首先要添加一块磁盘，在VMware中的设置里添加一块磁盘，在这里分配为20G。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171951.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213171951.png" alt="20151213171951"></a><a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172007.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172007.png" alt="20151213172007"></a> 在FreeNAS设置界面中，添加扩展设备。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172115.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172115.png" alt="20151213172115"></a> 7.关联目标 将用户信息和磁盘信息关联起来。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172143.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172143.png" alt="20151213172143"></a> 通过以上流程，我们便完成了一个网络硬盘的配置。</p>
      <h2 id="Windows使用"><a href="#Windows使用" class="headerlink" title="Windows使用"></a>Windows使用</h2>
      <p>好，配置好了网络硬盘，那么我们就在Windows下使用一下吧，Windows 7 以上的系统自带了 iSCSI 服务。 我们可以直接在控制面板里面找到它。在控制面板中搜索。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172329.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172329.png" alt="20151213172329"></a> 然后，会出现一个属性设置窗口。点击发现，发现门户，输入刚才FreeNAS的地址即可。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172518.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172518.png" alt="20151213172518"></a> 接下来在目标的选项卡中我们会看到刚才配置的一个目标，点击下方的连接即可。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172541.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172541.png" alt="20151213172541"></a> 连接成功之后，我们便可以完成连接了。 打开磁盘设置，我们便可以看到那个20G的磁盘了，然后新建简单卷。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172806.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172806.png" alt="20151213172806"></a> 格式化为NTFS系统，刷新一下，打开计算机。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172840.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151213172840.png" alt="20151213172840"></a> 我们可以发现，一个新的网络磁盘便安装成功啦。 可以向其中放置任何文件，与其他的磁盘没有任何区别！</p>
      <h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2>
      <p>FreeNAS是一个非常强大的工具，在这里我们只涉及到了 iSCSI 服务的使用，还有更多等待着我们的探索，小伙伴们快来试验一下吧。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-12-13 17:42:50" itemprop="dateCreated datePublished" datetime="2015-12-13T17:42:50+08:00">2015-12-13</time>
    </span>
    <span id="/2286.html" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络探究四之使用FreeNAS提供网络硬盘" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>1.8k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2266.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> C/C++ <i class="label-arrow"></i>
      </a>
      <a href="/2266.html" class="post-title-link" itemprop="url">VS中OpenSSL环境配置示例</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>最近在研究信息安全，需要用到OpenSSL库，我用到的开发IDE是VS2012，所以，在这里也记录一下我配置VS2012的OpenSSL库的过程。</p>
      <h2 id="下载OpenSSL库"><a href="#下载OpenSSL库" class="headerlink" title="下载OpenSSL库"></a>下载OpenSSL库</h2>
      <p>OpenSSL库大家可以自行下载源码然后用ruby进行编译，另外我们也可以选择直接下载编译好的类库。 这里我们利用的后者，在此提供一个下载链接。 <a href="http://pan.baidu.com/s/1dEs1nxR" target="_blank" rel="noopener">OpenSSL-Win32</a> 下载完成之后解压，比如我的放到了D盘。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162627.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162627.png" alt="20151207162627"></a></p>
      <h2 id="新建项目"><a href="#新建项目" class="headerlink" title="新建项目"></a>新建项目</h2>
      <p>首先，我们找一段测试代码，在此利用的是 AES 算法的示例。</p>
      <figure class="highlight cpp">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;openssl/aes.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">char</span> key[<span class="number">16</span>+<span class="number">1</span>] = <span class="string">"my-key-i-choosed"</span>; <span class="comment">// 128bits key (应该是真正的随机数才好)</span></span><br><span class="line">	<span class="keyword">char</span> pt1[<span class="number">16</span>+<span class="number">5</span>+<span class="number">1</span>] = <span class="string">"0123456789abcdef12345"</span>;   <span class="comment">// 明文</span></span><br><span class="line">	<span class="keyword">char</span> ct[<span class="number">16</span>+<span class="number">5</span>+<span class="number">1</span>];  <span class="comment">// 密文</span></span><br><span class="line">	<span class="keyword">char</span> pt2[<span class="number">16</span>+<span class="number">5</span>+<span class="number">1</span>]; <span class="comment">// 解密后的明文</span></span><br><span class="line"></span><br><span class="line">	AES_KEY k;</span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">char</span> iv1[<span class="number">16</span>+<span class="number">1</span>] = &#123;<span class="string">"1023456789abcdef"</span>&#125;; <span class="comment">// 16+1，加密用</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">char</span> iv2[<span class="number">16</span>+<span class="number">1</span>] = &#123;<span class="string">"1023456789abcdef"</span>&#125;; <span class="comment">// 16+1，解密用</span></span><br><span class="line"></span><br><span class="line">	&#123;	<span class="comment">// single blcok test</span></span><br><span class="line">		AES_set_encrypt_key(key, <span class="number">16</span>*<span class="number">8</span>, &amp;k); </span><br><span class="line">		AES_encrypt((<span class="keyword">unsigned</span> <span class="keyword">char</span>*)pt1, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)ct, &amp;k);</span><br><span class="line"></span><br><span class="line">		AES_set_decrypt_key(key, <span class="number">16</span>*<span class="number">8</span>, &amp;k);</span><br><span class="line">		AES_decrypt((<span class="keyword">unsigned</span> <span class="keyword">char</span>*)ct, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)pt2, &amp;k);</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (<span class="built_in">memcmp</span>(pt1, pt2, <span class="number">16</span>)==<span class="number">0</span>)</span><br><span class="line">			<span class="built_in">puts</span>(<span class="string">"AES block ok"</span>);</span><br><span class="line">		<span class="keyword">else</span></span><br><span class="line">			<span class="built_in">puts</span>(<span class="string">"AES block err"</span>);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	&#123;	<span class="comment">// cfb mode (stream mode)</span></span><br><span class="line">		<span class="keyword">int</span> num=<span class="number">0</span>;</span><br><span class="line">		AES_set_encrypt_key(key, <span class="number">16</span>*<span class="number">8</span>, &amp;k); </span><br><span class="line">		AES_cfb128_encrypt((<span class="keyword">unsigned</span> <span class="keyword">char</span>*)pt1, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)ct,</span><br><span class="line">			<span class="number">16</span>+<span class="number">5</span>, &amp;k, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)iv1, &amp;num, AES_ENCRYPT);</span><br><span class="line"></span><br><span class="line">		num=<span class="number">0</span>;</span><br><span class="line">		AES_set_encrypt_key(key, <span class="number">16</span>*<span class="number">8</span>, &amp;k); <span class="comment">// MUST as enc</span></span><br><span class="line">		AES_cfb128_encrypt((<span class="keyword">unsigned</span> <span class="keyword">char</span>*)ct, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)pt2,</span><br><span class="line">			<span class="number">16</span>+<span class="number">5</span>, &amp;k, (<span class="keyword">unsigned</span> <span class="keyword">char</span>*)iv2, &amp;num, AES_DECRYPT);		</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (<span class="built_in">memcmp</span>(pt1, pt2, <span class="number">16</span>+<span class="number">5</span>)==<span class="number">0</span>)</span><br><span class="line">			<span class="built_in">puts</span>(<span class="string">"AES CFB mode ok"</span>);</span><br><span class="line">		<span class="keyword">else</span></span><br><span class="line">			<span class="built_in">puts</span>(<span class="string">"AES CFB mode err"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	system(<span class="string">"pause"</span>);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>接下来新建一个项目，win32控制台程序，空项目，完成。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207161749.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207161749.png" alt="20151207161749"></a> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207161824.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207161824.png" alt="20151207161824"></a> 新建源文件，我取名叫做 aes.cpp，将代码复制进去，可以看到代码最初是在报错的。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162418.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162418.png" alt="20151207162418"></a> 好，接下来我们进行环境配置。</p>
      <h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2>
      <p>右键项目名称，弹出一个菜单，选择属性。 在VC++目录选项卡中，添加包含目录和库目录。 在这里，我的包含目录就是刚才解压的OpenSSL目录的include目录，库目录则是lib目录。 <strong>注意：分号要是英文分号，英文分号！</strong> <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162929.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207162929.png" alt="20151207162929"></a> 接下来选择连接器选项卡，输入libeay.lib和ssleay32.lib两个附加依赖项。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207163915.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207163915.png" alt="20151207163915"></a> 现在右击项目，重新生成。 我们可以看到，程序可以正常生成exe了。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164034.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164034.png" alt="20151207164034"></a> 但是直接运行的话会报错，是因为缺少dll文件。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164304.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164304.png" alt="20151207164304"></a> 之后，将项目中的libeay32.dll和ssleay32.dll文件放入项目的debug目录即可。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164444.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164444.png" alt="20151207164444"></a> 最后项目的debug目录如下 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164405.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164405.png" alt="20151207164405"></a> 重新运行exe程序，发现已经正常运行。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164736.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/12/20151207164736.png" alt="20151207164736"></a> 至此，VS配置OpenSSL环境的过程已经全部完成。 其他项目类似，大家可以试着配一下。 如有问题，欢迎留言交流~</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-12-07 16:50:54" itemprop="dateCreated datePublished" datetime="2015-12-07T16:50:54+08:00">2015-12-07</time>
    </span>
    <span id="/2266.html" class="post-meta-item leancloud_visitors" data-flag-title="VS中OpenSSL环境配置示例" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>1.9k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2249.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Linux <i class="label-arrow"></i>
      </a>
      <a href="/2249.html" class="post-title-link" itemprop="url">WordPress从Apache迁移到Apache过程</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>最近服务器要过期了，需要进行迁移，新服务器如果上面配置的是Apache服务器该怎么办呢？ 系统：Ubuntu 14.04</p>
      <h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2>
      <p>首先新主机上配置好apache环境，这个就不多说了，直接执行下面的命令即可。</p>
      <figure class="highlight smali">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo apt-get install apache2</span><br><span class="line">sudo apt-get install php5 php5-cgi php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-pspell php5-recode php5-snmp php5-tidy php5-xmlrpc php5-sqlite php5-xsl</span><br><span class="line">sudo apt-get install mysql-server mysql-client</span><br><span class="line">sudo apt-get install libapache2-mod-php5</span><br><span class="line">sudo apt-get install libapache2-mod-auth-mysql</span><br><span class="line">sudo apt-get install phpmyadmin</span><br><span class="line">sudo ln -s /usr/share/phpmyadmin/ /var/www/html/phpmyadmin</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>通过以上配置，新主机便可以实现lamp环境的配置了。</p>
      <h2 id="代码迁移"><a href="#代码迁移" class="headerlink" title="代码迁移"></a>代码迁移</h2>
      <p>首先旧主主机上打包一下代码，比如一个文件夹名字叫 wonder</p>
      <figure class="highlight css">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="selector-tag">tar</span> <span class="selector-tag">-zcvf</span> <span class="selector-tag">wonder</span><span class="selector-class">.tar</span><span class="selector-class">.gz</span> <span class="selector-tag">wonder</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后，打包完成之后，便会出现一个名字叫做 wonder.tar.gz 的文件 可以利用wget方式直接下载。</p>
      <figure class="highlight groovy">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">wget <span class="string">http:</span><span class="comment">//xxx.xxx.xxx.xxx/wonder.tar.gz</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>下载完成之后，直接解压即可。 这样代码就取到了。</p>
      <h2 id="数据库迁移"><a href="#数据库迁移" class="headerlink" title="数据库迁移"></a>数据库迁移</h2>
      <p>数据库迁移无非就是在phpmyadmin之间导入导出，这个很简单。 但是重要的一点是，需要把 wp-options 表中的两个URL配置改掉，比如原来是一个域名链接，现在需要改为 IP+文件名。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128144223.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128144223-1024x351.png" alt="20151128144223"></a> 否则，浏览器会提示重定向循环的问题。</p>
      <h2 id="服务器配置"><a href="#服务器配置" class="headerlink" title="服务器配置"></a>服务器配置</h2>
      <p>首先我们需要将域名解析到这个主机。 配置示例域名：wonderlee.me <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128144413.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128144413.png" alt="20151128144413"></a> 然后配置一下，vhost，在apache下配置是这样的 首先在 /etc/apache2/apache2.conf 中加入如下两行</p>
      <figure class="highlight autoit">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="meta"># <span class="meta-keyword">Include</span> all the user configurations:</span></span><br><span class="line">Include httpd.conf</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后我们需要在 httpd.conf 配置一下域名解析 新建一个 /etc/apach2/httpd.conf，加入如下内容</p>
      <figure class="highlight angelscript">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">ServerName <span class="number">115.28</span><span class="number">.24</span><span class="number">.44</span>:<span class="number">80</span></span><br><span class="line"></span><br><span class="line">&lt;VirtualHost <span class="number">115.28</span><span class="number">.24</span><span class="number">.44</span>:<span class="number">80</span>&gt; </span><br><span class="line">  DocumentRoot /var/www/html</span><br><span class="line">  ServerName   <span class="number">115.28</span><span class="number">.24</span><span class="number">.44</span></span><br><span class="line">&lt;/VirtualHost&gt; </span><br><span class="line"></span><br><span class="line">&lt;VirtualHost <span class="number">115.28</span><span class="number">.24</span><span class="number">.44</span>:<span class="number">80</span>&gt; </span><br><span class="line">  DocumentRoot /var/www/html/wonder</span><br><span class="line">  ServerName   wonderlee.me</span><br><span class="line">  ServerAlias  wonderlee.me</span><br><span class="line">&lt;/VirtualHost&gt;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后执行服务器重启操作。</p>
      <figure class="highlight routeros">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo<span class="built_in"> service </span>apache2 restart</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>好，这样的话我们的域名配置解析就好了。 输入 wonderlee.me 即可解析到 wonder 文件夹啦。 可以输入你的域名试试看，已经可以了吧。 然后我们需要开启 rewrite模块。 输入命令</p>
      <figure class="highlight coq">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo a2enmod <span class="built_in">rewrite</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后修改 /etc/apache2/apache2.conf 文件</p>
      <figure class="highlight apache">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="section">&lt;Directory /var/www/&gt;</span></span><br><span class="line">	<span class="attribute"><span class="nomarkup">Options</span></span> Indexes FollowSymLinks</span><br><span class="line">	<span class="attribute">AllowOverride</span> None</span><br><span class="line">	<span class="attribute">Require</span> <span class="literal">all</span> granted</span><br><span class="line"><span class="section">&lt;/Directory&gt;</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>改为</p>
      <figure class="highlight apache">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="section">&lt;Directory /var/www/&gt;</span></span><br><span class="line">	<span class="attribute"><span class="nomarkup">Options</span></span> Indexes FollowSymLinks</span><br><span class="line">	<span class="attribute">AllowOverride</span> <span class="literal">All</span></span><br><span class="line">	<span class="attribute">Require</span> <span class="literal">all</span> granted</span><br><span class="line"><span class="section">&lt;/Directory&gt;</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>即可，结束之后重启一下服务器。</p>
      <figure class="highlight routeros">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo<span class="built_in"> service </span>apache2 restart</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>在项目目录下新建一个文件 .htaccess，来支持重写</p>
      <figure class="highlight apache">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="comment"># BEGIN WordPress</span></span><br><span class="line"><span class="section">&lt;IfModule mod_rewrite.c&gt;</span></span><br><span class="line"><span class="attribute"><span class="nomarkup">RewriteEngine</span></span> <span class="literal">On</span></span><br><span class="line"><span class="attribute">RewriteBase</span> /wonder/</span><br><span class="line"><span class="attribute"><span class="nomarkup">RewriteRule</span></span> ^index\.php$ -<span class="meta"> [L]</span></span><br><span class="line"><span class="attribute"><span class="nomarkup">RewriteCond</span></span> <span class="variable">%&#123;REQUEST_FILENAME&#125;</span> !-f</span><br><span class="line"><span class="attribute"><span class="nomarkup">RewriteCond</span></span> <span class="variable">%&#123;REQUEST_FILENAME&#125;</span> !-d</span><br><span class="line"><span class="attribute"><span class="nomarkup">RewriteRule</span></span> . /wonder/index.php<span class="meta"> [L]</span></span><br><span class="line"><span class="section">&lt;/IfModule&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># END WordPress</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>好，这样，重写过程就完成啦。</p>
      <h2 id="网站配置"><a href="#网站配置" class="headerlink" title="网站配置"></a>网站配置</h2>
      <p>最后，需要将网站的配置修改一下，比如固定链接 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128145507.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128145507.png" alt="20151128145507"></a> 比如网站的基地址 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128145620.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151128145620.png" alt="20151128145620"></a> 至此，网站配置工作全部完成，欢乐地上网体验一下吧 如有问题，欢迎留言。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-11-28 14:59:07" itemprop="dateCreated datePublished" datetime="2015-11-28T14:59:07+08:00">2015-11-28</time>
    </span>
    <span id="/2249.html" class="post-meta-item leancloud_visitors" data-flag-title="WordPress从Apache迁移到Apache过程" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>2.2k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2227.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Linux <i class="label-arrow"></i>
      </a>
      <a href="/2227.html" class="post-title-link" itemprop="url">WordPress从Apache迁移到Nginx过程</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>之前一直都用Apache服务器，由于网站访问量比较大，另外加上旧服务器快到期了，准备迁移到新的服务器上，所以决定采用Nginx服务器。 迁移过程比较心酸，之前一直用apache，对nginx服务器配置不熟悉，踩了很多坑。下面说一下我的网站从旧主机（配有apache服务器）迁移到新主机（配有nginx服务器）的过程。</p>
      <h2 id="代码迁移"><a href="#代码迁移" class="headerlink" title="代码迁移"></a>代码迁移</h2>
      <p>这个过程其实也是比较心酸的，查看了一下目录结构占用空间已经足足快1个G了，可想而知里面占用的大部分空间是上传的图片素材。 不过要是迁移全部图片的话工程量实在是巨大。不过，好消息是我从开始就使用了七牛CDN加速，所以，上传的图片会自动存放到七牛，只不过也在主机本地留了备份而已，所以，我可以安心地删掉它们了。 那么对代码进行瘦身之后，这里就有两种方法来迁移了： 1.可以用git上传到github，然后用另一台主机把代码拉下来即可，在此不再赘述。 2.打包上传，然后直接在另一台主机上下载下来，由于我的两台主机在同一局域网内，所以我直接采用了这种方式，传输速度快。</p>
      <h3 id="打包"><a href="#打包" class="headerlink" title="打包"></a>打包</h3>
      <p>由于代码中含有 .git 目录，所以这部分我们不需要打包，那么压缩时我们就需要排除这个文件夹。 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151113155701-e1447401563242.png" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/11/20151113155701-e1447401563242.png" alt="20151113155701"></a> 文件夹名叫cqc，那么我们就打包一下，排除.git目录，使用如下命令</p>
      <figure class="highlight stylus">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">tar -zcvf cqc<span class="selector-class">.tar</span><span class="selector-class">.gz</span> --exclude=cqc/<span class="selector-class">.git</span> cqc</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>运行结束后会出现 cqc.tar.gz 文件，这就是目录压缩包。 然后我们只需要在另一台主机上输入</p>
      <figure class="highlight groovy">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">wget <span class="string">http:</span><span class="comment">//xxx.xxx.xxx.xxx/cqc.tar.gz</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>即可完成下载，速度可是嗖嗖的 然后解压即可，代码便完成了迁移。</p>
      <h2 id="数据库迁移"><a href="#数据库迁移" class="headerlink" title="数据库迁移"></a>数据库迁移</h2>
      <p>数据库用二者的phpmyadmin导出和上传即可。我导出 .sql 文件，大小为9M，而phpMyAdmin的上传限制大小是2M，怎么办？其实我们可以压缩 .sql 文件为 zip格式，压缩之后就有了1.4M了，分分钟完成上传。要知道 phpMyAdmin 可是支持 .sql.zip 文件的。 接下来是一个比较重要的部分，那就是配置一下站点信息。直接修改数据库的两个URL。 分别是 siteurl 和 home，一定要修改为 <a href="http://xxx.xxx.xxx.xxx/cqc" target="_blank" rel="noopener">http://xxx.xxx.xxx.xxx/cqc</a> 的形式，也就是把原来的域名改成IP加目录的形式，要不然网站是无法访问的，会出现多重循环定向的提示。 好，其他的没什么问题，连接数据库错误的话就修改一下目录的 wp-config.php 文件吧，连接数据库的信息修改正确就好了。</p>
      <h2 id="配置vhosts"><a href="#配置vhosts" class="headerlink" title="配置vhosts"></a>配置vhosts</h2>
      <p>和 apache 一样，我们多个域名肯定要可以解析到不同的目录吧，nginx 当然也是支持的。 接下来我们需要把新域名解析到 cqc 目录，在 nginx 下怎么做呢？其实还是比较简单的。 在 /etc/nginx 目录下可以新建一个 vhosts文件夹。在这里我们要解析 cqc 目录，那么我就新建一个 cqc.conf 文件。 现在例如我要把 blog.cuiqingcai.com 解析到 cqc 文件夹，配置如下</p>
      <figure class="highlight nginx">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">	<span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">	<span class="attribute">server_name</span> cuiqingcai.com blog.cuiqingcai.com;</span><br><span class="line">	</span><br><span class="line">	<span class="attribute">index</span> index.html index.htm index.php;</span><br><span class="line">	<span class="attribute">root</span> /var/www/cqc;</span><br><span class="line">	</span><br><span class="line">	<span class="attribute">location</span> / &#123;</span><br><span class="line">		</span><br><span class="line">		<span class="attribute">if</span> (!-e <span class="variable">$request_filename</span>) &#123;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^([_0-9a-zA-Z-]+)?(/wp-.*)</span> <span class="variable">$2</span> <span class="literal">last</span>;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^([_0-9a-zA-Z-]+)?(/.*\.php)$</span> <span class="variable">$2</span> <span class="literal">last</span>;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^</span> /index.php <span class="literal">last</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="attribute">location</span> <span class="regexp">~ \.php$</span> &#123;</span><br><span class="line">		<span class="attribute">fastcgi_pass</span> <span class="number">127.0.0.1:9000</span>;</span><br><span class="line">	<span class="comment">#	# With php5-fpm:</span></span><br><span class="line">	<span class="comment">#	fastcgi_pass unix:/var/run/php5-fpm.sock;</span></span><br><span class="line">		<span class="attribute">fastcgi_index</span> index.php;</span><br><span class="line">		<span class="attribute">fastcgi_param</span> SCRIPT_FILENAME /var/www/cqc<span class="variable">$fastcgi_script_name</span>;</span><br><span class="line">		<span class="attribute">include</span> fastcgi_params;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>其中</p>
      <figure class="highlight nginx">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="attribute">location</span> / &#123;</span><br><span class="line">		</span><br><span class="line">		<span class="attribute">if</span> (!-e <span class="variable">$request_filename</span>) &#123;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^([_0-9a-zA-Z-]+)?(/wp-.*)</span> <span class="variable">$2</span> <span class="literal">last</span>;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^([_0-9a-zA-Z-]+)?(/.*\.php)$</span> <span class="variable">$2</span> <span class="literal">last</span>;</span><br><span class="line">			<span class="attribute">rewrite</span><span class="regexp"> ^</span> /index.php <span class="literal">last</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>这一部分是伪静态重写，因为我的博客用的是wordpress，所以伪静态重写是这样的。当然还有其他的重写方式可以尝试。 之后在 /etc/nginx/nginx.conf 中的 http{} 中添加一行</p>
      <figure class="highlight gradle">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">include</span> <span class="regexp">/etc/</span>nginx<span class="regexp">/vhosts/</span>cqc.conf;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>则代表引用了这个文件。 注意，还要把 域名设置一下，添加一条A记录到主机上。 好了，一切大功告成了。</p>
      <h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2>
      <p>迁移和配置的过程坑实在是太多了，列列吧，警醒世人呐。 （1）代码迁移过程上传git，整个项目差不多1个G，由于数据量太大，导致内存不够无法正常上传。后来删除了图片，发现项目还是很大，结果发现是 .git 目录已经占用了上百兆，后来打包排除这个目录迁移的。 （2）数据库迁移的时候由于phpMyAdmin上传大小限制，修改了一番上传大小结果发现没生效，还倒腾了一下php-fpm，后来发现可以直接上传压缩包，那就分分钟完成了。 （3）配置完之后发现网站首页正常访问了，可是其他页面全部出现了404错误，后来配置了一番伪静态解析发现配置代码直接写在了 localhost server里面，后来发现可以直接新写一个 server，然后配置域名servername，然后配置伪静态重写才成功。 总之，坎坷是多，但是，自己慢慢摸索出来，也是一种不错的体验。 当你成功之后，会觉得世界又是那么美好。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-11-13 16:59:27" itemprop="dateCreated datePublished" datetime="2015-11-13T16:59:27+08:00">2015-11-13</time>
    </span>
    <span id="/2227.html" class="post-meta-item leancloud_visitors" data-flag-title="WordPress从Apache迁移到Nginx过程" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>2.5k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>2 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2200.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Java <i class="label-arrow"></i>
      </a>
      <a href="/2200.html" class="post-title-link" itemprop="url">Android开发之2048安卓版</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <p>之前是在eclipse上写的，后面换成了android sudio。 2048游戏的UI整体可以采用线性布局，即LinearLayout，其中嵌套一个线性布局和一个GridLayout，内嵌的线性布局填充文本框，以显示分数，GridLayout中填充4x4的继承自FrameLayout的card类作为主要的游戏界面。由于大部分操作都在GridLayout中进行，可以自定义一个继承自GridLayout的类GameView，类中定义判定上下左右滑动的方法和每次滑动后自动添加一个随机数字的方法以及每次滑动后判断游戏是否可以继续进行的方法。 主布局activity_main.xml代码如下</p>
      <figure class="highlight stylus">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">&lt;LinearLayout xmlns:android=<span class="string">"http://schemas.android.com/apk/res/android"</span></span><br><span class="line">    xmlns:tools=<span class="string">"http://schemas.android.com/tools"</span></span><br><span class="line">    android:id=<span class="string">"@+id/container"</span></span><br><span class="line">	<span class="comment">//match_parent表示布局充满整个屏幕</span></span><br><span class="line">    android:layout_width=<span class="string">"match_parent"</span></span><br><span class="line">    android:layout_height=<span class="string">"match_parent"</span></span><br><span class="line">    tools:context=<span class="string">"com.example.administractor.game2048.MainActivity"</span></span><br><span class="line">	<span class="comment">//里面的组件垂直放置</span></span><br><span class="line">    android:orientation=<span class="string">"vertical"</span></span><br><span class="line">    tools:ignore=<span class="string">"MergeRootFrame"</span>&gt;</span><br><span class="line"></span><br><span class="line">    &lt;LinearLayout</span><br><span class="line">	<span class="comment">//宽度充满整个屏幕，高度自适应。</span></span><br><span class="line">        android:layout_width=<span class="string">"fill_parent"</span></span><br><span class="line">        android:layout_height=<span class="string">"wrap_content"</span></span><br><span class="line">        android:orientation=<span class="string">"horizontal"</span> &gt;</span><br><span class="line">		<span class="comment">//显示当前分数的文本框</span></span><br><span class="line">        &lt;TextView android:layout_width=<span class="string">"wrap_content"</span></span><br><span class="line">            android:layout_height=<span class="string">"wrap_content"</span></span><br><span class="line">            android:text=<span class="string">"Your Score:"</span>/&gt;</span><br><span class="line">        &lt;TextView</span><br><span class="line">            android:id=<span class="string">"@+id/tvScore"</span></span><br><span class="line">            android:layout_width=<span class="string">"wrap_content"</span></span><br><span class="line">            android:layout_height=<span class="string">"wrap_content"</span>/&gt;</span><br><span class="line">    &lt;/LinearLayout&gt;</span><br><span class="line">	<span class="comment">//使用自定义的GridLayout</span></span><br><span class="line">    &lt;com<span class="selector-class">.example</span><span class="selector-class">.administractor</span><span class="selector-class">.game2048</span>.GameView</span><br><span class="line">        android:layout_width=<span class="string">"fill_parent"</span></span><br><span class="line">        android:layout_height=<span class="string">"0dp"</span></span><br><span class="line">        android:layout_weight=<span class="string">"1"</span></span><br><span class="line">        android:id=<span class="string">"@+id/GameView"</span> &gt;</span><br><span class="line">    &lt;/com<span class="selector-class">.example</span><span class="selector-class">.administractor</span><span class="selector-class">.game2048</span>.GameView&gt;</span><br><span class="line">&lt;/LinearLayout&gt;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>GameView.java：</p>
      <figure class="highlight reasonml">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">package com.example.administrator.game2048;</span><br><span class="line"></span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line"></span><br><span class="line">import android.app.AlertDialog;</span><br><span class="line">import android.content.Context;</span><br><span class="line">import android.content.DialogInterface;</span><br><span class="line">import android.graphics.Point;</span><br><span class="line">import android.util.AttributeSet;</span><br><span class="line">import android.view.MotionEvent;</span><br><span class="line">import android.view.View;</span><br><span class="line">import android.widget.GridLayout;</span><br><span class="line"></span><br><span class="line">public <span class="keyword">class</span> GameView extends GridLayout &#123;</span><br><span class="line"><span class="comment">//调用类构造方法</span></span><br><span class="line">    public <span class="constructor">GameView(Context <span class="params">context</span>, AttributeSet <span class="params">attrs</span>, <span class="params">int</span> <span class="params">defStyle</span>)</span> &#123;</span><br><span class="line">        super(context, attrs, defStyle);</span><br><span class="line">        <span class="comment">//初始化游戏</span></span><br><span class="line">		<span class="constructor">InitGameView()</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public <span class="constructor">GameView(Context <span class="params">context</span>, AttributeSet <span class="params">attrs</span>)</span> &#123;</span><br><span class="line">        super(context, attrs);</span><br><span class="line">        <span class="constructor">InitGameView()</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public <span class="constructor">GameView(Context <span class="params">context</span>)</span> &#123;</span><br><span class="line">        super(context);</span><br><span class="line">        <span class="constructor">InitGameView()</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> void <span class="constructor">InitGameView()</span>&#123;</span><br><span class="line">		<span class="comment">//设置为4x4个方格</span></span><br><span class="line">        set<span class="constructor">ColumnCount(4)</span>;</span><br><span class="line">		<span class="comment">//设置背景颜色</span></span><br><span class="line">        set<span class="constructor">BackgroundColor(0xffeee4da)</span>;</span><br><span class="line"></span><br><span class="line">		<span class="comment">//判定滑动方向</span></span><br><span class="line">        set<span class="constructor">OnTouchListener(<span class="params">new</span> OnTouchListener()</span> &#123;</span><br><span class="line">            <span class="keyword">private</span> <span class="built_in">float</span> startx,starty,offsetx,offsety;</span><br><span class="line">            @Override</span><br><span class="line">            public boolean on<span class="constructor">Touch(View <span class="params">v</span>, MotionEvent <span class="params">event</span>)</span> &#123;</span><br><span class="line">                switch(event.get<span class="constructor">Action()</span>)&#123;</span><br><span class="line">                    case MotionEvent.ACTION_DOWN:</span><br><span class="line">                        startx=event.get<span class="constructor">X()</span>;</span><br><span class="line">                        starty=event.get<span class="constructor">Y()</span>;</span><br><span class="line">                        break;</span><br><span class="line">                    case MotionEvent.ACTION_UP:</span><br><span class="line">                        offsetx=event.get<span class="constructor">X()</span>-startx;</span><br><span class="line">                        offsety=event.get<span class="constructor">Y()</span>-starty;</span><br><span class="line">                        <span class="keyword">if</span>(<span class="module-access"><span class="module"><span class="identifier">Math</span>.</span></span>abs(offsetx)&gt;<span class="module-access"><span class="module"><span class="identifier">Math</span>.</span></span>abs(offsety))&#123;</span><br><span class="line">                            <span class="keyword">if</span>(offsetx&lt;-<span class="number">5</span>)&#123;</span><br><span class="line">                                swipe<span class="constructor">Left()</span>;</span><br><span class="line">                            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(offsetx&gt;<span class="number">5</span>)&#123;</span><br><span class="line">                                swipe<span class="constructor">Right()</span>;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                            <span class="keyword">if</span>(offsety&lt;-<span class="number">5</span>)&#123;</span><br><span class="line">                                swipe<span class="constructor">Up()</span>;</span><br><span class="line">                            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(offsetx&gt;<span class="number">3</span>)&#123;</span><br><span class="line">                                swipe<span class="constructor">Down()</span>;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                        break;</span><br><span class="line">                &#125;</span><br><span class="line">                return <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//适应不同大小的屏幕</span></span><br><span class="line">    @Override</span><br><span class="line">    protected void on<span class="constructor">SizeChanged(<span class="params">int</span> <span class="params">w</span>, <span class="params">int</span> <span class="params">h</span>, <span class="params">int</span> <span class="params">oldw</span>, <span class="params">int</span> <span class="params">oldh</span>)</span> &#123;</span><br><span class="line">        super.on<span class="constructor">SizeChanged(<span class="params">w</span>, <span class="params">h</span>, <span class="params">oldw</span>, <span class="params">oldh</span>)</span>;</span><br><span class="line">        <span class="built_in">int</span> cardWidth=(<span class="module-access"><span class="module"><span class="identifier">Math</span>.</span></span>min(h, w))/<span class="number">4</span>;</span><br><span class="line">        add<span class="constructor">Cards(<span class="params">cardWidth</span>,<span class="params">cardWidth</span>)</span>;</span><br><span class="line">        start<span class="constructor">Game()</span>;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//在4x4的方格上添加满卡片</span></span><br><span class="line">    public void add<span class="constructor">Cards(<span class="params">int</span> <span class="params">cardwidth</span>,<span class="params">int</span> <span class="params">cardheight</span>)</span>&#123;</span><br><span class="line">        Card c;</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">                c=<span class="keyword">new</span> <span class="constructor">Card(<span class="params">getContext</span>()</span>);</span><br><span class="line">                c.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                add<span class="constructor">View(<span class="params">c</span>, <span class="params">cardwidth</span>, <span class="params">cardheight</span>)</span>;</span><br><span class="line">                cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>=c;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//游戏开始时每个卡片默认值设为0，并随机添加两张带数字的卡片</span></span><br><span class="line">    <span class="keyword">private</span> void start<span class="constructor">Game()</span>&#123;</span><br><span class="line">        <span class="module-access"><span class="module"><span class="identifier">MainActivity</span>.</span></span>get<span class="constructor">MainActivity()</span>.clear<span class="constructor">Score()</span>;</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">                cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        add<span class="constructor">RandomNum()</span>;</span><br><span class="line">        add<span class="constructor">RandomNum()</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> void add<span class="constructor">RandomNum()</span> &#123;</span><br><span class="line">		<span class="comment">//使用emptypoints将数字为0的card提取出来，并随即选择一个空card赋值</span></span><br><span class="line">        emptyPoints.clear<span class="literal">()</span>;</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">                <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">                    emptyPoints.add(<span class="keyword">new</span> <span class="constructor">Point(<span class="params">x</span>,<span class="params">y</span>)</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        Point p=emptyPoints.remove((<span class="built_in">int</span>)(<span class="module-access"><span class="module"><span class="identifier">Math</span>.</span></span>random<span class="literal">()</span>*emptyPoints.size<span class="literal">()</span>));</span><br><span class="line">		<span class="comment">//2和4出现的概率控制在1：9</span></span><br><span class="line">        cardmap<span class="literal">[<span class="identifier">p</span>.<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">p</span>.<span class="identifier">y</span>]</span>.set<span class="constructor">Num(Math.<span class="params">random</span>()</span>&gt;<span class="number">0.1</span>?<span class="number">2</span>:<span class="number">4</span>);</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//左滑方法</span></span><br><span class="line">    <span class="keyword">private</span> void swipe<span class="constructor">Left()</span>&#123;</span><br><span class="line">		<span class="comment">//merge作为判断能否滑动的flag</span></span><br><span class="line">        boolean merge = <span class="literal">false</span>;</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">                for (<span class="built_in">int</span> x1 = x+<span class="number">1</span>; x1 &lt;<span class="number">4</span>; x1++) &#123;</span><br><span class="line">                    <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&gt;<span class="number">0</span>)&#123;</span><br><span class="line">                        <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x1</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            merge=<span class="literal">true</span>;</span><br><span class="line">                            x--;</span><br><span class="line">                        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.equal(cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>))&#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>*<span class="number">2</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            <span class="module-access"><span class="module"><span class="identifier">MainActivity</span>.</span></span>get<span class="constructor">MainActivity()</span>.add<span class="constructor">Score(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            merge=<span class="literal">true</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        break;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(merge)&#123;</span><br><span class="line">            add<span class="constructor">RandomNum()</span>;</span><br><span class="line">            check<span class="constructor">Complete()</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//下滑</span></span><br><span class="line">    <span class="keyword">private</span> void swipe<span class="constructor">Down()</span>&#123;</span><br><span class="line"></span><br><span class="line">        boolean merge = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> y = <span class="number">3</span>; y &gt;=<span class="number">0</span>; y--) &#123;</span><br><span class="line"></span><br><span class="line">                for (<span class="built_in">int</span> y1 = y-<span class="number">1</span>; y1 &gt;=<span class="number">0</span>; y1--) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.get<span class="constructor">Num()</span>&gt;<span class="number">0</span>) &#123;</span><br><span class="line"></span><br><span class="line">                        <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&lt;=<span class="number">0</span>) &#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y1</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line"></span><br><span class="line">                            y++;</span><br><span class="line">                            merge = <span class="literal">true</span>;</span><br><span class="line">                        &#125;<span class="keyword">else</span> <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.equal(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>)) &#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>*<span class="number">2</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            <span class="module-access"><span class="module"><span class="identifier">MainActivity</span>.</span></span>get<span class="constructor">MainActivity()</span>.add<span class="constructor">Score(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            merge = <span class="literal">true</span>;</span><br><span class="line">                        &#125;</span><br><span class="line"></span><br><span class="line">                        break;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (merge) &#123;</span><br><span class="line">            add<span class="constructor">RandomNum()</span>;</span><br><span class="line">            check<span class="constructor">Complete()</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//上滑</span></span><br><span class="line">    <span class="keyword">private</span> void swipe<span class="constructor">Up()</span>&#123;</span><br><span class="line"></span><br><span class="line">        boolean merge = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; <span class="number">4</span>; x++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line"></span><br><span class="line">                for (<span class="built_in">int</span> y1 = y+<span class="number">1</span>; y1 &lt; <span class="number">4</span>; y1++) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.get<span class="constructor">Num()</span>&gt;<span class="number">0</span>) &#123;</span><br><span class="line"></span><br><span class="line">                        <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&lt;=<span class="number">0</span>) &#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y1</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line"></span><br><span class="line">                            y--;</span><br><span class="line"></span><br><span class="line">                            merge = <span class="literal">true</span>;</span><br><span class="line">                        &#125;<span class="keyword">else</span> <span class="keyword">if</span> (cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.equal(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>)) &#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>*<span class="number">2</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y1</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            <span class="module-access"><span class="module"><span class="identifier">MainActivity</span>.</span></span>get<span class="constructor">MainActivity()</span>.add<span class="constructor">Score(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            merge = <span class="literal">true</span>;</span><br><span class="line">                        &#125;</span><br><span class="line"></span><br><span class="line">                        break;</span><br><span class="line"></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (merge) &#123;</span><br><span class="line">            add<span class="constructor">RandomNum()</span>;</span><br><span class="line">            check<span class="constructor">Complete()</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//右滑</span></span><br><span class="line">    <span class="keyword">private</span> void swipe<span class="constructor">Right()</span>&#123;</span><br><span class="line">        boolean merge = <span class="literal">false</span>;</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; <span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">3</span>; x &gt;=<span class="number">0</span>; x--) &#123;</span><br><span class="line">                for (<span class="built_in">int</span> x1 = x-<span class="number">1</span>; x1 &gt;=<span class="number">0</span>; x1--) &#123;</span><br><span class="line">                    <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&gt;<span class="number">0</span>)&#123;</span><br><span class="line">                        <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x1</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            x++;</span><br><span class="line">                            merge=<span class="literal">true</span>;</span><br><span class="line">                        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.equal(cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>))&#123;</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>*<span class="number">2</span>);</span><br><span class="line">                            cardmap<span class="literal">[<span class="identifier">x1</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.set<span class="constructor">Num(0)</span>;</span><br><span class="line">                            <span class="module-access"><span class="module"><span class="identifier">MainActivity</span>.</span></span>get<span class="constructor">MainActivity()</span>.add<span class="constructor">Score(<span class="params">cardmap</span>[<span class="params">x</span>][<span class="params">y</span>].<span class="params">getNum</span>()</span>);</span><br><span class="line">                            merge=<span class="literal">true</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        break;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(merge)&#123;</span><br><span class="line">            add<span class="constructor">RandomNum()</span>;</span><br><span class="line">            check<span class="constructor">Complete()</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//如果有空卡片或者相邻的值相同卡片则游戏还能进行</span></span><br><span class="line">    public void check<span class="constructor">Complete()</span>&#123;</span><br><span class="line">        boolean complete=<span class="literal">true</span>;</span><br><span class="line">        ALL:</span><br><span class="line">        for (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt;<span class="number">4</span>; y++) &#123;</span><br><span class="line">            for (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt;<span class="number">4</span>; x++) &#123;</span><br><span class="line">                <span class="keyword">if</span>(cardmap<span class="literal">[<span class="identifier">x</span>]</span><span class="literal">[<span class="identifier">y</span>]</span>.get<span class="constructor">Num()</span>==<span class="number">0</span><span class="pattern-match"><span class="operator">||</span></span></span><br><span class="line"><span class="pattern-match">                        x&gt;0<span class="operator">&amp;&amp;</span>cardmap[x][y].equal(cardmap[x-1][y])<span class="operator">||</span></span></span><br><span class="line"><span class="pattern-match">                        x&lt;3<span class="operator">&amp;&amp;</span>cardmap[x][y].equal(cardmap[x+1][y])<span class="operator">||</span></span></span><br><span class="line"><span class="pattern-match">                        y&gt;0<span class="operator">&amp;&amp;</span>cardmap[x][y].equal(cardmap[x][y-1])<span class="operator">||</span></span></span><br><span class="line"><span class="pattern-match">                        y&lt;3<span class="operator">&amp;&amp;</span>cardmap[x][y].equal(cardmap[x][y+1]))&#123;</span></span><br><span class="line"><span class="pattern-match">                    complete=<span class="literal">false</span>;</span></span><br><span class="line"><span class="pattern-match">                    break <span class="constructor">ALL</span>;</span></span><br><span class="line"><span class="pattern-match">                &#125;</span></span><br><span class="line"><span class="pattern-match">            &#125;</span></span><br><span class="line"><span class="pattern-match">        &#125;</span></span><br><span class="line"><span class="pattern-match">		<span class="operator">/</span><span class="operator">/</span>游戏结束弹出alert提示窗口</span></span><br><span class="line"><span class="pattern-match">        <span class="keyword">if</span>(complete)&#123;</span></span><br><span class="line"><span class="pattern-match">            <span class="keyword">new</span> <span class="constructor">AlertDialog</span>.<span class="constructor">Builder(<span class="params">getContext</span>()</span>).set<span class="constructor">Title(<span class="string">"大林哥温馨提示"</span>)</span>.set<span class="constructor">Message(<span class="string">"游戏结束"</span>)</span>.set<span class="constructor">PositiveButton(<span class="string">"重来"</span>,<span class="params">new</span> DialogInterface.OnClickListener()</span> &#123;</span></span><br><span class="line"><span class="pattern-match"></span></span><br><span class="line"><span class="pattern-match">                @<span class="constructor">Override</span></span></span><br><span class="line"><span class="pattern-match">                public void on<span class="constructor">Click(DialogInterface <span class="params">arg0</span>, <span class="params">int</span> <span class="params">arg1</span>)</span> &#123;</span></span><br><span class="line"><span class="pattern-match">                    start<span class="constructor">Game()</span>;</span></span><br><span class="line"><span class="pattern-match">                &#125;</span></span><br><span class="line"><span class="pattern-match">            &#125;).show();</span></span><br><span class="line"><span class="pattern-match">        &#125;</span></span><br><span class="line"><span class="pattern-match"></span></span><br><span class="line"><span class="pattern-match">    &#125;</span></span><br><span class="line"><span class="pattern-match">    <span class="keyword">private</span> <span class="constructor">Card</span>[][] cardmap=<span class="keyword">new</span> <span class="constructor">Card</span>[4][4];</span></span><br><span class="line"><span class="pattern-match">    <span class="keyword">private</span> <span class="constructor">List</span>&lt;<span class="constructor">Point</span>&gt; empty<span class="constructor">Points</span>=<span class="keyword">new</span> <span class="constructor">ArrayList</span>&lt;<span class="constructor">Point</span>&gt;();</span></span><br><span class="line"><span class="pattern-match">&#125;</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>主类MainActivity.java：</p>
      <figure class="highlight java">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">package</span> com.example.administrator.game2048;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.app.Activity;</span><br><span class="line"><span class="keyword">import</span> android.os.Bundle;</span><br><span class="line"><span class="keyword">import</span> android.widget.TextView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">Activity</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MainActivity</span><span class="params">()</span></span>&#123;</span><br><span class="line">        mainActivity=<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        tvscore = (TextView) findViewById(R.id.tvScore);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">clearScore</span><span class="params">()</span></span>&#123;</span><br><span class="line">        score=<span class="number">0</span>;</span><br><span class="line">        showScore();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">showScore</span><span class="params">()</span></span>&#123;</span><br><span class="line">        tvscore.setText(score+<span class="string">""</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addScore</span><span class="params">(<span class="keyword">int</span> s)</span></span>&#123;</span><br><span class="line">        score+=s;</span><br><span class="line">        showScore();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> TextView tvscore;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> score=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> MainActivity mainActivity=<span class="keyword">null</span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> MainActivity <span class="title">getMainActivity</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> mainActivity;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>Card.java：</p>
      <figure class="highlight angelscript">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">package com.example.administrator.game2048;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> android.content.Context;</span><br><span class="line"><span class="keyword">import</span> android.view.Gravity;</span><br><span class="line"><span class="keyword">import</span> android.view.View;</span><br><span class="line"><span class="keyword">import</span> android.widget.FrameLayout;</span><br><span class="line"><span class="keyword">import</span> android.widget.TextView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="symbol">Card</span> <span class="symbol">extends</span> <span class="symbol">FrameLayout</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Card(Context context) &#123;</span><br><span class="line">        <span class="keyword">super</span>(context);</span><br><span class="line">        LayoutParams lp = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">        View background = new View(getContext());</span><br><span class="line">		<span class="comment">//参数-1表示layoutparams填充满整个父容器</span></span><br><span class="line">        lp = new LayoutParams(<span class="number">-1</span>, <span class="number">-1</span>);</span><br><span class="line">		<span class="comment">//设置卡片之间有10像素的间隔</span></span><br><span class="line">        lp.setMargins(<span class="number">10</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        background.setBackgroundColor(<span class="number">0x33ffffff</span>);</span><br><span class="line">        addView(background, lp);</span><br><span class="line"></span><br><span class="line">        label = new TextView(getContext());</span><br><span class="line">        label.setTextSize(<span class="number">28</span>);</span><br><span class="line">        label.setGravity(Gravity.CENTER);</span><br><span class="line"></span><br><span class="line">        lp = new LayoutParams(<span class="number">-1</span>, <span class="number">-1</span>);</span><br><span class="line">        lp.setMargins(<span class="number">10</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        addView(label, lp);</span><br><span class="line"></span><br><span class="line">        setNum(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="built_in">int</span> n=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> getNum()&#123;</span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//设置数字及对应的背景颜色</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">void</span> setNum(<span class="built_in">int</span> n)&#123;</span><br><span class="line">        <span class="keyword">this</span>.n=n;</span><br><span class="line">        <span class="keyword">if</span>(n&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">            label.setText(<span class="string">""</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            label.setText(n+<span class="string">""</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">switch</span> (n) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0x00000000</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffeee4da</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">4</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffede0c8</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">8</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xfff2b179</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">16</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xfff59563</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">32</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xfff67c5f</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">64</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xfff65e3b</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">128</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffedcf72</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">256</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffedcc61</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">512</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffedc850</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">1024</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffedc53f</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">2048</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xffedc22e</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                label.setBackgroundColor(<span class="number">0xff3c3a32</span>);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="comment">//判断卡片是否相等</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">bool</span>ean equal(Card o)&#123;</span><br><span class="line">        <span class="keyword">return</span> getNum()==o.getNum();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> TextView label;</span><br><span class="line">&#125;</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p> <img src="http://img.blog.csdn.net/20151031225217834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""> <img src="http://img.blog.csdn.net/20151031225316437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/大龄锅" class="author" itemprop="url" rel="index">大龄锅</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-11-07 15:06:58" itemprop="dateCreated datePublished" datetime="2015-11-07T15:06:58+08:00">2015-11-07</time>
    </span>
    <span id="/2200.html" class="post-meta-item leancloud_visitors" data-flag-title="Android开发之2048安卓版" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>10k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>9 分钟</span>
    </span>
  </div>
</article>

    <article itemscope itemtype="http://schema.org/Article" class="post-block index" lang="zh-CN">
  <link itemprop="mainEntityOfPage" href="https://cuiqingcai.com/2188.html">
  <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="image" content="/images/avatar.png">
    <meta itemprop="name" content="崔庆才">
    <meta itemprop="description" content="崔庆才的个人站点，记录生活的瞬间，分享学习的心得。">
  </span>
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="静觅">
  </span>
  <header class="post-header">
    <h2 class="post-title" itemprop="name headline">
      <a class="label"> Net <i class="label-arrow"></i>
      </a>
      <a href="/2188.html" class="post-title-link" itemprop="url">计算机网络探究三之搭建并连接VPN服务器</a>
    </h2>
  </header>
  <div class="post-body" itemprop="articleBody">
    <div class="thumb">
      <img itemprop="contentUrl" class="random">
    </div>
    <div class="excerpt">
      <p>
      <h2 id="openvpn原理"><a href="#openvpn原理" class="headerlink" title="openvpn原理"></a>openvpn原理</h2>
      <p>VPN直译就是虚拟专用通道，是提供给企业之间或者个人与公司之间安全数据传输的隧道，OpenVPN无疑是Linux下开源VPN的先锋，提供了良好的性能和友好的用户GUI。 它大量使用了OpenSSL加密库中的SSLv3/TLSv1协议函数库。 目前OpenVPN能在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X与Microsoft Windows以及Android和iOS上运行，并包含了许多安全性的功能。它并不是一个基于Web的VPN软件，也不与IPsec及其他VPN软件包兼容。 openvpn通过使用公开密钥（非对称密钥，加密解密使用不同的key，一个称为Publice key，另外一个是Private key）对数据进行加密的。这种方式称为TLS加密。 openvpn使用TLS加密的工作过程是，首先VPN Sevrver端和VPN Client端要有相同的CA证书，双方通过交换证书验证双方的合法性，用于决定是否建立VPN连接。 然后使用对方的CA证书，把自己目前使用的数据加密方法加密后发送给对方，由于使用的是对方CA证书加密，所以只有对方CA证书对应的Private key才能解密该数据，这样就保证了此密钥的安全性，并且此密钥是定期改变的，对于窃听者来说，可能还没有破解出此密钥，VPN通信双方可能就已经更换密钥了。 扩展阅读： <a href="http://baike.baidu.com/link?url=ssl8SkkfVHTcjm9UCzJ8AsJOhIHMYcxuIisO4pqyqaZF6llwP1r0fgLvYEmAg_zYhFWauFzfEyXmEmFcaprG2K" target="_blank" rel="noopener">openvpn</a></p>
      <h2 id="安装openvpn"><a href="#安装openvpn" class="headerlink" title="安装openvpn"></a>安装openvpn</h2>
      <p>首先，你需要有一台长期运行的服务器，大家可以用自己的闲置的电脑或者买一台阿里云啦。 我的服务器是Ubuntu 14.04，下面就演示一下我的配置过程。 安装</p>
      <figure class="highlight q">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo apt-<span class="built_in">get</span> -y install openvpn libssl-<span class="built_in">dev</span> openssl</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>查看下版本并记录下来</p>
      <figure class="highlight ada">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">openvpn <span class="comment">--version</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p><a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030145358.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030145358.jpg" alt="20151030145358"></a> 在这里我们的版本是2.3.2</p>
      <h2 id="安装easy-rsa"><a href="#安装easy-rsa" class="headerlink" title="安装easy-rsa"></a>安装easy-rsa</h2>
      <p>easy-rsa是用来制作openvpn相关证书的，使用如下命令安装</p>
      <figure class="highlight routeros">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo apt-<span class="builtin-name">get</span> -y install easy-rsa</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>好，一切准备就绪后，我们就开始制作证书啦，我们需要制作的有三个证书 CA证书、Server端证书、Client端证书。行动起来。</p>
      <h2 id="制作CA证书"><a href="#制作CA证书" class="headerlink" title="制作CA证书"></a>制作CA证书</h2>
      <p>openvpn与easy-rsa安装完毕后，我们需要在/etc/openvpn/目录下创建easy-rsa文件夹，如下</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo mkdir <span class="regexp">/etc/</span>openvpn<span class="regexp">/easy-rsa/</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>然后把/usr/share/easy-rsa/目录下的所有文件全部复制到/etc/openvpn/easy-rsa/下</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo cp -r <span class="regexp">/usr/</span>share<span class="regexp">/easy-rsa/</span>* <span class="regexp">/etc/</span>openvpn<span class="regexp">/easy-rsa/</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>当然，我们也可以直接在/usr/share/easy-rsa/制作相关的证书，但是为了后续的管理证书的方便，我们还是把easy-rsa放在了openvpn的启动目录下。 <strong>注意：由于我们现在使用的是ubuntu系统，所以我们必须切换到root用户下才能制作相关证书，否则easy-rsa会报错。如果是centos系统，则不存在此问题。</strong> 切换到root用户下，使用如下命令：</p>
      <figure class="highlight ebnf">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="attribute">sudo su</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>在开始制作CA证书之前，我们还需要编辑vars文件，修改如下相关选项内容即可</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo vi <span class="regexp">/etc/</span>openvpn<span class="regexp">/easy-rsa/</span>vars</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <figure class="highlight routeros">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_COUNTRY</span>=<span class="string">"CN"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_PROVINCE</span>=<span class="string">"SD"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_CITY</span>=<span class="string">"JiNan"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_ORG</span>=<span class="string">"germy"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_EMAIL</span>=<span class="string">"cqc@cuiqingcai.com"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_OU</span>=<span class="string">"germy"</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">KEY_NAME</span>=<span class="string">"germy"</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>如图所示 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030150125.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030150125.jpg" alt="20151030150125"></a> 之后，我们需要利用这个文件来制作我们的证书，保存一下。 然后一个很重要的一步，赋予权限，否则在制作证书的时候，值还是初始化的值。</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo chmod <span class="number">777</span> <span class="regexp">/etc/</span>openvpn<span class="regexp">/easy-rsa/</span>vars</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>vars文件主要用于设置证书的相关组织信息，红色部分的内容可以根据自己的实际情况自行修改。 其中export KEY_NAME=”germy” 这个要记住下，我们下面在制作Server端证书时，会使用到。 <strong>注意：以上内容，我们也可以使用系统默认的，也就是说不进行修改也是可以使用的。</strong> 然后使用source vars命令使其生效，如下：</p>
      <figure class="highlight vim">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">source</span> vars</span><br><span class="line">./clean-<span class="keyword">all</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>注意：执行clean-all命令会删除，当前目录下的keys文件夹。 现在开始正式制作CA证书，使用如下命令：</p>
      <figure class="highlight jboss-cli">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">cd</span> <span class="string">/etc/openvpn/easy-rsa/</span></span><br><span class="line"><span class="string">./build-ca</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>一路回车即可。 制作完成后，我们可以查看keys目录里有什么东西。 如果你的目录下出现了ca.crt和ca.key两个文件，其中ca.crt就是我们所说的CA证书。如此，CA证书制作完毕。 现在把该CA证书的ca.crt文件复制到openvpn的启动目录/etc/openvpn下，如下：</p>
      <figure class="highlight vim">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="keyword">cp</span> <span class="built_in">keys</span>/<span class="keyword">ca</span>.crt /etc/openvpn/</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <h2 id="制作Server端证书"><a href="#制作Server端证书" class="headerlink" title="制作Server端证书"></a>制作Server端证书</h2>
      <p>CA证书制作完成后，我们现在开始制作Server端证书。如下：</p>
      <figure class="highlight n1ql">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">./<span class="keyword">build</span>-<span class="keyword">key</span>-server germy</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>上述命令中germy，就是我们前面vars文件中设置的KEY_NAME 查看 keys 目录 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030150704.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030150704.jpg" alt="20151030150704"></a> 如果可以发现出现了 germy.crt，germy.csr，germy.key 文件，就说明成功了。 现在再为服务器生成加密交换时的Diffie-Hellman文件，如下：</p>
      <figure class="highlight jboss-cli">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="string">./build-dh</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>你会发现目录下多了一个 dh2048.pem 文件。 以上操作完毕后，把germy.crt，germy.key，dh2048.pem 复制到 /etc/openvpn/ 目录下，如下：</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">cd <span class="regexp">/etc/</span>openvpn<span class="regexp">/easy-rsa/</span></span><br><span class="line">cp keys<span class="regexp">/germy.crt keys/g</span>ermy.key keys<span class="regexp">/dh2048.pem /</span>etc<span class="regexp">/openvpn/</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>如此，Server端证书就制作完毕。</p>
      <h2 id="制作Client端证书"><a href="#制作Client端证书" class="headerlink" title="制作Client端证书"></a>制作Client端证书</h2>
      <p>Server端证书制作完成后，我们现在开始制作Client端证书，如下：</p>
      <figure class="highlight n1ql">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">./<span class="keyword">build</span>-<span class="keyword">key</span> cqc</span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>其中上述命令的cqc就是客户端证书名称，可以自定义 如果发现keys目录已经生成了cqc.csr、cqc.crt和cqc.key这个三个文件。其中cqc.crt和cqc.key两个文件是我们要使用的。 如此，Client端证书就制作完毕。</p>
      <h2 id="配置Server端"><a href="#配置Server端" class="headerlink" title="配置Server端"></a>配置Server端</h2>
      <p>所有证书制作完毕后，我们现在开始配置Server端。Server端的配置文件，我们可以从openvpn自带的模版中进行复制。如下：</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">cp <span class="regexp">/usr/</span>share<span class="regexp">/doc/</span>openvpn<span class="regexp">/examples/</span>sample-config-files<span class="regexp">/server.conf.gz /</span>etc<span class="regexp">/openvpn/</span></span><br><span class="line">cd <span class="regexp">/etc/</span>openvpn<span class="regexp">/</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>解压server.conf.gz 文件，使用如下命令：</p>
      <figure class="highlight css">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="selector-tag">gzip</span> <span class="selector-tag">-d</span> <span class="selector-tag">server</span><span class="selector-class">.conf</span><span class="selector-class">.gz</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>注意：上述命令的意思是解压server.conf.gz文件后，然后删除原文件。 现在我们来修改server.conf文件 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030151728.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030151728.jpg" alt="20151030151728"></a> 一共要修改3处文件 （1）修改了openvpn运行时使用的协议，由原来的UDP协议修改为TCP协议。生成环境建议使用TCP协议。 （2）修改了openvpn服务器的相关证书，由原来的server.csr、server.key修改为germy.crt、germy.key。 （3）修改了Diffie-Hellman文件，由原来的dh1024.pem修改为dh2048.pem。 配置文件修改完毕后，我们现在来启动openvpn，使用如下命令：</p>
      <figure class="highlight awk">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="regexp">/etc/i</span>nit.d<span class="regexp">/openvpn start</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>至此，服务器端的VPN已经配置完毕了。</p>
      <h2 id="客户端的配置"><a href="#客户端的配置" class="headerlink" title="客户端的配置"></a>客户端的配置</h2>
      <p>服务器端配置好了，我们需要用另一台机器来连接，这里我们的客户端依然是Ubuntu 14.04 首先我们需要从服务器上取到刚才生成的证书文件，那么我们需要的有什么呢？ <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030152200.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030152200.jpg" alt="20151030152200"></a> 首先这三个，ca.crt，cqc.crt，cqc.key 另外是一个模板，它是 /usr/share/doc/openvpn/examples/sample-config-files/client.conf 把这四个文件下载下来，然后放到客户端里。 比如我们保存到客户机的 home/user 文件夹下 <a href="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030152421.jpg" target="_blank" rel="noopener"><img src="http://qiniu.cuiqingcai.com/wp-content/uploads/2015/10/20151030152421.jpg" alt="20151030152421"></a> 把 client.conf 文件重命名为 client.ovpn 然后修改下面4处</p>
      <figure class="highlight css">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="selector-tag">proto</span> <span class="selector-tag">tcp</span></span><br><span class="line"><span class="selector-tag">remote</span> 121<span class="selector-class">.42</span><span class="selector-class">.14</span><span class="selector-class">.158</span> 1194</span><br><span class="line"><span class="selector-tag">ca</span> <span class="selector-tag">ca</span><span class="selector-class">.crt</span></span><br><span class="line"><span class="selector-tag">cert</span> <span class="selector-tag">cqc</span><span class="selector-class">.crt</span></span><br><span class="line"><span class="selector-tag">key</span> <span class="selector-tag">cqc</span><span class="selector-class">.key</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>其中 remote 就是你的服务器地址 配置好了之后，我们运行</p>
      <figure class="highlight ada">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line">sudo openvpn <span class="comment">--config client.ovpn</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>如果最后的结果是 Sequence Completed 那就证明连接成功啦。 输入</p>
      <figure class="highlight ebnf">
        <table>
          <tr>
            <td class="gutter">
              <pre><span class="line">1</span><br></pre>
            </td>
            <td class="code">
              <pre><span class="line"><span class="attribute">ifconfig</span></span><br></pre>
            </td>
          </tr>
        </table>
      </figure>
      <p>你会发现多了一个tun0适配器，这就是openvpn的适配器。 至此，openvpn的配置和连接就全部完成啦。</p>
      <h2 id="参考来源"><a href="#参考来源" class="headerlink" title="参考来源"></a>参考来源</h2>
      <p><a href="http://www.myhack58.com/Article/sort099/sort0102/2015/65155_4.htm" target="_blank" rel="noopener">参考文献</a> 如有问题，欢迎留言交流。</p>
      </p>
    </div>
  </div>
  <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-user"></i>
      </span>
      <span class="post-meta-item-text">作者</span>
      <span><a href="/authors/崔庆才" class="author" itemprop="url" rel="index">崔庆才</a></span>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      <time title="创建时间：2015-10-30 15:33:28" itemprop="dateCreated datePublished" datetime="2015-10-30T15:33:28+08:00">2015-10-30</time>
    </span>
    <span id="/2188.html" class="post-meta-item leancloud_visitors" data-flag-title="计算机网络探究三之搭建并连接VPN服务器" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>3.7k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>3 分钟</span>
    </span>
  </div>
</article>



  <script>
  document.querySelectorAll('.random').forEach(item => item.src="https://picsum.photos/id/" + Math.floor(Math.random() * Math.floor(300)) + "/200/133")
  </script>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/23/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/23/">23</a><span class="page-number current">24</span><a class="page-number" href="/page/25/">25</a><span class="space">&hellip;</span><a class="page-number" href="/page/31/">31</a><a class="extend next" rel="next" href="/page/25/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
<div class="toggle sidebar-toggle">
  <span class="toggle-line toggle-line-first"></span>
  <span class="toggle-line toggle-line-middle"></span>
  <span class="toggle-line toggle-line-last"></span>
</div>

<aside class="sidebar">
  <div class="sidebar-inner">

    <ul class="sidebar-nav motion-element">
      <li class="sidebar-nav-toc">
        文章目录
      </li>
      <li class="sidebar-nav-overview">
        站点概览
      </li>
    </ul>

    <!--noindex-->
    <div class="post-toc-wrap sidebar-panel">
    </div>
    <!--/noindex-->

    <div class="site-overview-wrap sidebar-panel">
      <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <img class="site-author-image" itemprop="image" alt="崔庆才" src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">崔庆才</p>
  <div class="site-description" itemprop="description">崔庆才的个人站点，记录生活的瞬间，分享学习的心得。</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
    <div class="site-state-item site-state-posts">
      <a href="/archives/">
        <span class="site-state-item-count">608</span>
        <span class="site-state-item-name">日志</span>
      </a>
    </div>
    <div class="site-state-item site-state-categories">
      <a href="/categories/">
        <span class="site-state-item-count">24</span>
        <span class="site-state-item-name">分类</span></a>
    </div>
    <div class="site-state-item site-state-tags">
      <a href="/tags/">
        <span class="site-state-item-count">156</span>
        <span class="site-state-item-name">标签</span></a>
    </div>
  </nav>
</div>
<div class="links-of-author motion-element">
  <span class="links-of-author-item">
    <a href="https://github.com/Germey" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Germey" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
  </span>
  <span class="links-of-author-item">
    <a href="mailto:cqc@cuiqingcai.com.com" title="邮件 → mailto:cqc@cuiqingcai.com.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>邮件</a>
  </span>
  <span class="links-of-author-item">
    <a href="https://weibo.com/cuiqingcai" title="微博 → https:&#x2F;&#x2F;weibo.com&#x2F;cuiqingcai" rel="noopener" target="_blank"><i class="fab fa-weibo fa-fw"></i>微博</a>
  </span>
  <span class="links-of-author-item">
    <a href="https://www.zhihu.com/people/Germey" title="知乎 → https:&#x2F;&#x2F;www.zhihu.com&#x2F;people&#x2F;Germey" rel="noopener" target="_blank"><i class="fa fa-magic fa-fw"></i>知乎</a>
  </span>
</div>

    </div>
    <div
      style=" width: 100%;"
      class="sidebar-panel sidebar-panel-image sidebar-panel-active">
      <a href="https://tutorial.lengyue.video/?coupon=12ef4b1a-a3db-11ea-bb37-0242ac130002_cqx_850" target="_blank" rel="noopener">
        <img src="https://qiniu.cuiqingcai.com/bco2a.png"
             style=" width: 100%;">
      </a>
    </div>
    <div
      style=" width: 100%;"
      class="sidebar-panel sidebar-panel-image sidebar-panel-active">
      <a href="http://www.ipidea.net/?utm-source=cqc&utm-keyword=?cqc" target="_blank" rel="noopener">
        <img src="https://qiniu.cuiqingcai.com/0ywun.png"
             style=" width: 100%;">
      </a>
    </div>
    <div class="sidebar-panel sidebar-panel-tags sidebar-panel-active">
      <h4 class="name">
        标签云
      </h4>
      <div class="content">
        <a href="/tags/2048/" style="font-size: 10px;">2048</a> <a href="/tags/API/" style="font-size: 10px;">API</a> <a href="/tags/Bootstrap/" style="font-size: 11.25px;">Bootstrap</a> <a href="/tags/CDN/" style="font-size: 10px;">CDN</a> <a href="/tags/CQC/" style="font-size: 10px;">CQC</a> <a href="/tags/CSS/" style="font-size: 10px;">CSS</a> <a href="/tags/CSS-%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 10px;">CSS 反爬虫</a> <a href="/tags/CV/" style="font-size: 10px;">CV</a> <a href="/tags/Django/" style="font-size: 10px;">Django</a> <a href="/tags/Eclipse/" style="font-size: 11.25px;">Eclipse</a> <a href="/tags/FTP/" style="font-size: 10px;">FTP</a> <a href="/tags/Git/" style="font-size: 10px;">Git</a> <a href="/tags/GitHub/" style="font-size: 13.75px;">GitHub</a> <a href="/tags/HTML5/" style="font-size: 10px;">HTML5</a> <a href="/tags/Hexo/" style="font-size: 10px;">Hexo</a> <a href="/tags/IT/" style="font-size: 10px;">IT</a> <a href="/tags/JSP/" style="font-size: 10px;">JSP</a> <a href="/tags/JavaScript/" style="font-size: 10px;">JavaScript</a> <a href="/tags/K8s/" style="font-size: 10px;">K8s</a> <a href="/tags/LOGO/" style="font-size: 10px;">LOGO</a> <a href="/tags/Linux/" style="font-size: 10px;">Linux</a> <a href="/tags/MIUI/" style="font-size: 10px;">MIUI</a> <a href="/tags/MongoDB/" style="font-size: 10px;">MongoDB</a> <a href="/tags/Mysql/" style="font-size: 10px;">Mysql</a> <a href="/tags/NBA/" style="font-size: 10px;">NBA</a> <a href="/tags/PHP/" style="font-size: 11.25px;">PHP</a> <a href="/tags/PS/" style="font-size: 10px;">PS</a> <a href="/tags/Pathlib/" style="font-size: 10px;">Pathlib</a> <a href="/tags/PhantomJS/" style="font-size: 10px;">PhantomJS</a> <a href="/tags/Python/" style="font-size: 15px;">Python</a> <a href="/tags/Python3/" style="font-size: 12.5px;">Python3</a> <a href="/tags/Pythonic/" style="font-size: 10px;">Pythonic</a> <a href="/tags/QQ/" style="font-size: 10px;">QQ</a> <a href="/tags/Redis/" style="font-size: 10px;">Redis</a> <a href="/tags/SAE/" style="font-size: 10px;">SAE</a> <a href="/tags/SSH/" style="font-size: 10px;">SSH</a> <a href="/tags/SVG/" style="font-size: 10px;">SVG</a> <a href="/tags/Scrapy/" style="font-size: 10px;">Scrapy</a> <a href="/tags/Scrapy-redis/" style="font-size: 10px;">Scrapy-redis</a> <a href="/tags/Scrapy%E5%88%86%E5%B8%83%E5%BC%8F/" style="font-size: 10px;">Scrapy分布式</a> <a href="/tags/Selenium/" style="font-size: 10px;">Selenium</a> <a href="/tags/TKE/" style="font-size: 10px;">TKE</a> <a href="/tags/Ubuntu/" style="font-size: 11.25px;">Ubuntu</a> <a href="/tags/VS-Code/" style="font-size: 10px;">VS Code</a> <a href="/tags/Vs-Code/" style="font-size: 10px;">Vs Code</a> <a href="/tags/Vue/" style="font-size: 11.25px;">Vue</a> <a href="/tags/Webpack/" style="font-size: 10px;">Webpack</a> <a href="/tags/Windows/" style="font-size: 10px;">Windows</a> <a href="/tags/Winpcap/" style="font-size: 10px;">Winpcap</a> <a href="/tags/WordPress/" style="font-size: 13.75px;">WordPress</a> <a href="/tags/Youtube/" style="font-size: 11.25px;">Youtube</a> <a href="/tags/android/" style="font-size: 10px;">android</a> <a href="/tags/ansible/" style="font-size: 10px;">ansible</a> <a href="/tags/cocos2d-x/" style="font-size: 10px;">cocos2d-x</a> <a href="/tags/e6/" style="font-size: 10px;">e6</a> <a href="/tags/fitvids/" style="font-size: 10px;">fitvids</a> <a href="/tags/git/" style="font-size: 11.25px;">git</a> <a href="/tags/json/" style="font-size: 10px;">json</a> <a href="/tags/js%E9%80%86%E5%90%91/" style="font-size: 10px;">js逆向</a> <a href="/tags/kubernetes/" style="font-size: 10px;">kubernetes</a> <a href="/tags/log/" style="font-size: 10px;">log</a> <a href="/tags/logging/" style="font-size: 10px;">logging</a> <a href="/tags/matlab/" style="font-size: 11.25px;">matlab</a> <a href="/tags/python/" style="font-size: 20px;">python</a> <a href="/tags/pytube/" style="font-size: 11.25px;">pytube</a> <a href="/tags/pywin32/" style="font-size: 10px;">pywin32</a> <a href="/tags/style/" style="font-size: 10px;">style</a> <a href="/tags/tomcat/" style="font-size: 10px;">tomcat</a> <a href="/tags/ubuntu/" style="font-size: 10px;">ubuntu</a> <a href="/tags/uwsgi/" style="font-size: 10px;">uwsgi</a> <a href="/tags/vsftpd/" style="font-size: 10px;">vsftpd</a> <a href="/tags/wamp/" style="font-size: 10px;">wamp</a> <a href="/tags/wineQQ/" style="font-size: 10px;">wineQQ</a> <a href="/tags/%E4%B8%83%E7%89%9B/" style="font-size: 11.25px;">七牛</a> <a href="/tags/%E4%B8%8A%E6%B5%B7/" style="font-size: 10px;">上海</a> <a href="/tags/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/" style="font-size: 10px;">个人网站</a> <a href="/tags/%E4%B8%BB%E9%A2%98/" style="font-size: 10px;">主题</a> <a href="/tags/%E4%BA%91%E4%BA%A7%E5%93%81/" style="font-size: 10px;">云产品</a> <a href="/tags/%E4%BA%91%E5%AD%98%E5%82%A8/" style="font-size: 10px;">云存储</a> <a href="/tags/%E4%BA%AC%E4%B8%9C%E4%BA%91/" style="font-size: 10px;">京东云</a> <a href="/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/" style="font-size: 12.5px;">人工智能</a> <a href="/tags/%E4%BB%A3%E7%90%86/" style="font-size: 10px;">代理</a> <a href="/tags/%E4%BB%A3%E7%A0%81/" style="font-size: 10px;">代码</a> <a href="/tags/%E4%BB%A3%E7%A0%81%E5%88%86%E4%BA%AB%E5%9B%BE/" style="font-size: 10px;">代码分享图</a> <a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size: 10px;">优化</a> <a href="/tags/%E4%BD%8D%E8%BF%90%E7%AE%97/" style="font-size: 10px;">位运算</a> <a href="/tags/%E5%85%AC%E4%BC%97%E5%8F%B7/" style="font-size: 10px;">公众号</a> <a href="/tags/%E5%88%86%E4%BA%AB/" style="font-size: 10px;">分享</a> <a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F/" style="font-size: 10px;">分布式</a> <a href="/tags/%E5%88%9B%E4%B8%9A/" style="font-size: 10px;">创业</a> <a href="/tags/%E5%89%8D%E7%AB%AF/" style="font-size: 12.5px;">前端</a> <a href="/tags/%E5%8D%9A%E5%AE%A2/" style="font-size: 10px;">博客</a> <a href="/tags/%E5%8E%9F%E7%94%9FAPP/" style="font-size: 10px;">原生APP</a> <a href="/tags/%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 12.5px;">反爬虫</a> <a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size: 10px;">命令</a> <a href="/tags/%E5%93%8D%E5%BA%94%E5%BC%8F%E5%B8%83%E5%B1%80/" style="font-size: 10px;">响应式布局</a> <a href="/tags/%E5%9E%83%E5%9C%BE%E9%82%AE%E4%BB%B6/" style="font-size: 10px;">垃圾邮件</a> <a href="/tags/%E5%9F%9F%E5%90%8D%E7%BB%91%E5%AE%9A/" style="font-size: 10px;">域名绑定</a> <a href="/tags/%E5%A4%8D%E7%9B%98/" style="font-size: 10px;">复盘</a> <a href="/tags/%E5%A4%A7%E4%BC%97%E7%82%B9%E8%AF%84/" style="font-size: 10px;">大众点评</a> <a href="/tags/%E5%AD%97%E4%BD%93%E5%8F%8D%E7%88%AC%E8%99%AB/" style="font-size: 10px;">字体反爬虫</a> <a href="/tags/%E5%AD%97%E7%AC%A6%E9%97%AE%E9%A2%98/" style="font-size: 10px;">字符问题</a> <a href="/tags/%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/" style="font-size: 10px;">学习方法</a> <a href="/tags/%E5%AE%89%E5%8D%93/" style="font-size: 10px;">安卓</a> <a href="/tags/%E5%AE%9E%E7%94%A8/" style="font-size: 10px;">实用</a> <a href="/tags/%E5%B0%81%E9%9D%A2/" style="font-size: 10px;">封面</a> <a href="/tags/%E5%B4%94%E5%BA%86%E6%89%8D/" style="font-size: 18.75px;">崔庆才</a> <a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size: 12.5px;">工具</a> <a href="/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/" style="font-size: 10px;">开发工具</a> <a href="/tags/%E5%BE%AE%E8%BD%AF/" style="font-size: 10px;">微软</a> <a href="/tags/%E6%80%9D%E8%80%83/" style="font-size: 10px;">思考</a> <a href="/tags/%E6%89%8B%E6%9C%BA%E8%AE%BF%E9%97%AE/" style="font-size: 10px;">手机访问</a> <a href="/tags/%E6%95%99%E7%A8%8B/" style="font-size: 10px;">教程</a> <a href="/tags/%E6%95%99%E8%82%B2/" style="font-size: 10px;">教育</a> <a href="/tags/%E6%96%B0%E4%B9%A6/" style="font-size: 12.5px;">新书</a> <a href="/tags/%E6%96%B9%E6%B3%95%E8%AE%BA/" style="font-size: 10px;">方法论</a> <a href="/tags/%E6%97%85%E6%B8%B8/" style="font-size: 10px;">旅游</a> <a href="/tags/%E6%97%A5%E5%BF%97/" style="font-size: 10px;">日志</a> <a href="/tags/%E6%9A%97%E6%97%B6%E9%97%B4/" style="font-size: 10px;">暗时间</a> <a href="/tags/%E6%9D%9C%E5%85%B0%E7%89%B9/" style="font-size: 11.25px;">杜兰特</a> <a href="/tags/%E6%A1%8C%E9%9D%A2/" style="font-size: 10px;">桌面</a> <a href="/tags/%E6%AD%8C%E5%8D%95/" style="font-size: 10px;">歌单</a> <a href="/tags/%E6%B1%9F%E5%8D%97/" style="font-size: 10px;">江南</a> <a href="/tags/%E6%B8%B8%E6%88%8F/" style="font-size: 10px;">游戏</a> <a href="/tags/%E7%84%A6%E8%99%91/" style="font-size: 10px;">焦虑</a> <a href="/tags/%E7%88%AC%E8%99%AB/" style="font-size: 16.25px;">爬虫</a> <a href="/tags/%E7%88%AC%E8%99%AB%E4%B9%A6%E7%B1%8D/" style="font-size: 11.25px;">爬虫书籍</a> <a href="/tags/%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F/" style="font-size: 10px;">环境变量</a> <a href="/tags/%E7%94%9F%E6%B4%BB%E7%AC%94%E8%AE%B0/" style="font-size: 10px;">生活笔记</a> <a href="/tags/%E7%99%BB%E5%BD%95/" style="font-size: 10px;">登录</a> <a href="/tags/%E7%9F%A5%E4%B9%8E/" style="font-size: 10px;">知乎</a> <a href="/tags/%E7%9F%AD%E4%BF%A1/" style="font-size: 10px;">短信</a> <a href="/tags/%E7%9F%AD%E4%BF%A1%E9%AA%8C%E8%AF%81%E7%A0%81/" style="font-size: 10px;">短信验证码</a> <a href="/tags/%E7%AC%94%E8%AE%B0%E8%BD%AF%E4%BB%B6/" style="font-size: 10px;">笔记软件</a> <a href="/tags/%E7%AF%AE%E7%BD%91/" style="font-size: 10px;">篮网</a> <a href="/tags/%E7%BA%B8%E5%BC%A0/" style="font-size: 10px;">纸张</a> <a href="/tags/%E7%BB%84%E4%BB%B6/" style="font-size: 10px;">组件</a> <a href="/tags/%E7%BD%91%E7%AB%99/" style="font-size: 10px;">网站</a> <a href="/tags/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/" style="font-size: 11.25px;">网络爬虫</a> <a href="/tags/%E7%BE%8E%E5%AD%A6/" style="font-size: 10px;">美学</a> <a href="/tags/%E8%82%89%E5%A4%B9%E9%A6%8D/" style="font-size: 10px;">肉夹馍</a> <a href="/tags/%E8%85%BE%E8%AE%AF%E4%BA%91/" style="font-size: 10px;">腾讯云</a> <a href="/tags/%E8%87%AA%E5%BE%8B/" style="font-size: 10px;">自律</a> <a href="/tags/%E8%A5%BF%E5%B0%91%E7%88%B7/" style="font-size: 10px;">西少爷</a> <a href="/tags/%E8%A7%86%E9%A2%91/" style="font-size: 10px;">视频</a> <a href="/tags/%E8%B0%B7%E6%AD%8C%E9%AA%8C%E8%AF%81%E7%A0%81/" style="font-size: 10px;">谷歌验证码</a> <a href="/tags/%E8%BF%90%E8%90%A5/" style="font-size: 10px;">运营</a> <a href="/tags/%E8%BF%9C%E7%A8%8B/" style="font-size: 10px;">远程</a> <a href="/tags/%E9%80%86%E5%90%91/" style="font-size: 10px;">逆向</a> <a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size: 10px;">配置</a> <a href="/tags/%E9%87%8D%E8%A3%85/" style="font-size: 10px;">重装</a> <a href="/tags/%E9%98%BF%E6%9D%9C/" style="font-size: 10px;">阿杜</a> <a href="/tags/%E9%9D%99%E8%A7%85/" style="font-size: 17.5px;">静觅</a> <a href="/tags/%E9%A2%A0%E8%A6%86/" style="font-size: 10px;">颠覆</a> <a href="/tags/%E9%A3%9E%E4%BF%A1/" style="font-size: 10px;">飞信</a> <a href="/tags/%E9%B8%BF%E8%92%99/" style="font-size: 10px;">鸿蒙</a>
      </div>
      <script>
        const tagsColors = ['#00a67c', '#5cb85c', '#d9534f', '#567e95', '#b37333', '#f4843d', '#15a287']
        const tagsElements = document.querySelectorAll('.sidebar-panel-tags .content a')
        tagsElements.forEach((item) => {
          item.style.backgroundColor = tagsColors[Math.floor(Math.random() * tagsColors.length)]
        })
      </script>
    </div>
    <div class="sidebar-panel sidebar-panel-categories sidebar-panel-active">
      <h4 class="name">
        分类
      </h4>
      <div class="content">
        <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/C-C/">C/C++</a><span class="category-list-count">23</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/HTML/">HTML</a><span class="category-list-count">14</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java/">Java</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/">JavaScript</a><span class="category-list-count">26</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Linux/">Linux</a><span class="category-list-count">15</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Markdown/">Markdown</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Net/">Net</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Other/">Other</a><span class="category-list-count">39</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/PHP/">PHP</a><span class="category-list-count">27</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Paper/">Paper</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Python/">Python</a><span class="category-list-count">261</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/TypeScript/">TypeScript</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E5%B1%95%E7%A4%BA/">个人展示</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E6%97%A5%E8%AE%B0/">个人日记</a><span class="category-list-count">9</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E8%AE%B0%E5%BD%95/">个人记录</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E4%B8%AA%E4%BA%BA%E9%9A%8F%E7%AC%94/">个人随笔</a><span class="category-list-count">15</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/">安装配置</a><span class="category-list-count">59</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/">技术杂谈</a><span class="category-list-count">88</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%9C%AA%E5%88%86%E7%B1%BB/">未分类</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%94%9F%E6%B4%BB%E7%AC%94%E8%AE%B0/">生活笔记</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%A6%8F%E5%88%A9%E4%B8%93%E5%8C%BA/">福利专区</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%81%8C%E4%BD%8D%E6%8E%A8%E8%8D%90/">职位推荐</a><span class="category-list-count">2</span></li></ul>
      </div>
    </div>
    <div class="sidebar-panel sidebar-panel-friends sidebar-panel-active">
      <h4 class="name">
        友情链接
      </h4>
      <ul class="friends">
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/j2dub.jpg">
          </span>
          <span class="link">
            <a href="https://www.findhao.net/" target="_blank" rel="noopener">FindHao</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/ou6mm.jpg">
          </span>
          <span class="link">
            <a href="https://diygod.me/" target="_blank" rel="noopener">DIYgod</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/6apxu.jpg">
          </span>
          <span class="link">
            <a href="https://www.51dev.com/" target="_blank" rel="noopener">IT技术社区</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://www.jankl.com/img/titleshu.jpg">
          </span>
          <span class="link">
            <a href="https://www.jankl.com/" target="_blank" rel="noopener">liberalist</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/bqlbs.png">
          </span>
          <span class="link">
            <a href="http://www.urselect.com/" target="_blank" rel="noopener">优社电商</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/8s88c.jpg">
          </span>
          <span class="link">
            <a href="https://www.yuanrenxue.com/" target="_blank" rel="noopener">猿人学</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/2wgg5.jpg">
          </span>
          <span class="link">
            <a href="https://www.yunlifang.cn/" target="_blank" rel="noopener">云立方</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/shwr6.png">
          </span>
          <span class="link">
            <a href="http://lanbing510.info/" target="_blank" rel="noopener">冰蓝</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/blvoh.jpg">
          </span>
          <span class="link">
            <a href="https://lengyue.me/" target="_blank" rel="noopener">冷月</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="http://qianxunclub.com/favicon.png">
          </span>
          <span class="link">
            <a href="http://qianxunclub.com/" target="_blank" rel="noopener">千寻啊千寻</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/0044u.jpg">
          </span>
          <span class="link">
            <a href="http://kodcloud.com/" target="_blank" rel="noopener">可道云</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/ygnpn.jpg">
          </span>
          <span class="link">
            <a href="http://www.kunkundashen.cn/" target="_blank" rel="noopener">坤坤大神</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/22uv1.png">
          </span>
          <span class="link">
            <a href="http://www.cenchong.com/" target="_blank" rel="noopener">岑冲博客</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/ev9kl.png">
          </span>
          <span class="link">
            <a href="http://www.zxiaoji.com/" target="_blank" rel="noopener">张小鸡</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://www.503error.com/favicon.ico">
          </span>
          <span class="link">
            <a href="https://www.503error.com/" target="_blank" rel="noopener">张志明个人博客</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/x714o.jpg">
          </span>
          <span class="link">
            <a href="http://www.hubwiz.com/" target="_blank" rel="noopener">汇智网</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/129d8.png">
          </span>
          <span class="link">
            <a href="https://www.bysocket.com/" target="_blank" rel="noopener">泥瓦匠BYSocket</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://www.xiongge.club/favicon.ico">
          </span>
          <span class="link">
            <a href="https://www.xiongge.club/" target="_blank" rel="noopener">熊哥club</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/3w4fe.png">
          </span>
          <span class="link">
            <a href="https://zerlong.com/" target="_blank" rel="noopener">知语</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/44hxf.png">
          </span>
          <span class="link">
            <a href="http://redstonewill.com/" target="_blank" rel="noopener">红色石头</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/8g1fk.jpg">
          </span>
          <span class="link">
            <a href="http://www.laodong.me/" target="_blank" rel="noopener">老董博客</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/wkaus.jpg">
          </span>
          <span class="link">
            <a href="https://zhaoshuai.me/" target="_blank" rel="noopener">碎念</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/pgo0r.jpg">
          </span>
          <span class="link">
            <a href="https://www.chenwenguan.com/" target="_blank" rel="noopener">陈文管的博客</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/kk82a.jpg">
          </span>
          <span class="link">
            <a href="https://www.lxlinux.net/" target="_blank" rel="noopener">良许Linux教程网</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/lj0t2.jpg">
          </span>
          <span class="link">
            <a href="https://tanqingbo.cn/" target="_blank" rel="noopener">IT码农</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/i8cdr.png">
          </span>
          <span class="link">
            <a href="https://junyiseo.com/" target="_blank" rel="noopener">均益个人博客</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/chwv2.png">
          </span>
          <span class="link">
            <a href="https://brucedone.com/" target="_blank" rel="noopener">大鱼的鱼塘</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/2y43o.png">
          </span>
          <span class="link">
            <a href="http://bbs.nightteam.cn/" target="_blank" rel="noopener">夜幕爬虫安全论坛</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/zvc3w.jpg">
          </span>
          <span class="link">
            <a href="https://www.weishidong.com/" target="_blank" rel="noopener">韦世东的技术专栏</a>
          </span>
        </li>
        <li class="friend">
          <span class="logo">
            <img src="https://qiniu.cuiqingcai.com/ebudy.jpg">
          </span>
          <span class="link">
            <a href="https://chuanjiabing.com/" target="_blank" rel="noopener">穿甲兵技术社区</a>
          </span>
        </li>
      </ul>
    </div>

  </div>
</aside>
<div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        <div class="copyright"> &copy; <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">崔庆才丨静觅</span>
  <span class="post-meta-divider">|</span>
  <span class="post-meta-item-icon">
    <i class="fa fa-chart-area"></i>
  </span>
  <span title="站点总字数">2.6m</span>
  <span class="post-meta-divider">|</span>
  <span class="post-meta-item-icon">
    <i class="fa fa-coffee"></i>
  </span>
  <span title="站点阅读时长">39:54</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> 强力驱动 </div>
<div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">京ICP备18015597号-1 </a>
</div>

        <script>
  (function ()
  {
    function leancloudSelector(url)
    {
      url = encodeURI(url);
      return document.getElementById(url).querySelector('.leancloud-visitors-count');
    }

    function addCount(Counter)
    {
      var visitors = document.querySelector('.leancloud_visitors');
      var url = decodeURI(visitors.id);
      var title = visitors.dataset.flagTitle;
      Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify(
      {
        url
      }))).then(response => response.json()).then((
      {
        results
      }) =>
      {
        if (results.length > 0)
        {
          var counter = results[0];
          leancloudSelector(url).innerText = counter.time + 1;
          Counter('put', '/classes/Counter/' + counter.objectId,
          {
            time:
            {
              '__op': 'Increment',
              'amount': 1
            }
          }).catch(error =>
          {
            console.error('Failed to save visitor count', error);
          });
        }
        else
        {
          Counter('post', '/classes/Counter',
          {
            title,
            url,
            time: 1
          }).then(response => response.json()).then(() =>
          {
            leancloudSelector(url).innerText = 1;
          }).catch(error =>
          {
            console.error('Failed to create', error);
          });
        }
      }).catch(error =>
      {
        console.error('LeanCloud Counter Error', error);
      });
    }

    function showTime(Counter)
    {
      var visitors = document.querySelectorAll('.leancloud_visitors');
      var entries = [...visitors].map(element =>
      {
        return decodeURI(element.id);
      });
      Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify(
      {
        url:
        {
          '$in': entries
        }
      }))).then(response => response.json()).then((
      {
        results
      }) =>
      {
        for (let url of entries)
        {
          let target = results.find(item => item.url === url);
          leancloudSelector(url).innerText = target ? target.time : 0;
        }
      }).catch(error =>
      {
        console.error('LeanCloud Counter Error', error);
      });
    }
    let
    {
      app_id,
      app_key,
      server_url
    } = {
      "enable": true,
      "app_id": "6X5dRQ0pnPWJgYy8SXOg0uID-gzGzoHsz",
      "app_key": "ziLDVEy73ne5HtFTiGstzHMS",
      "server_url": "https://6x5drq0p.lc-cn-n1-shared.com",
      "security": false
    };

    function fetchData(api_server)
    {
      var Counter = (method, url, data) =>
      {
        return fetch(`${api_server}/1.1${url}`,
        {
          method,
          headers:
          {
            'X-LC-Id': app_id,
            'X-LC-Key': app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      if (CONFIG.page.isPost)
      {
        if (CONFIG.hostname !== location.hostname) return;
        addCount(Counter);
      }
      else if (document.querySelectorAll('.post-title-link').length >= 1)
      {
        showTime(Counter);
      }
    }
    let api_server = app_id.slice(-9) !== '-MdYXbMMI' ? server_url : `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`;
    if (api_server)
    {
      fetchData(api_server);
    }
    else
    {
      fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id).then(response => response.json()).then((
      {
        api_server
      }) =>
      {
        fetchData('https://' + api_server);
      });
    }
  })();

</script>

      </div>
      <div class="footer-stat">
        <span id="cnzz_stat_icon_1279355174"></span>
        <script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1279355174'%3E%3C/span%3E%3Cscript src='https://v1.cnzz.com/z_stat.php%3Fid%3D1279355174%26online%3D1%26show%3Dline' type='text/javascript'%3E%3C/script%3E"));</script>
      </div>
    </footer>
  </div>

  <script src="//cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/.js"></script>
<script src="/js/next-boot.js"></script>
<script src="/.js"></script>

  <script>
  (function ()
  {
    var canonicalURL, curProtocol;
    //Get the <link> tag
    var x = document.getElementsByTagName("link");
    //Find the last canonical URL
    if (x.length > 0)
    {
      for (i = 0; i < x.length; i++)
      {
        if (x[i].rel.toLowerCase() == 'canonical' && x[i].href)
        {
          canonicalURL = x[i].href;
        }
      }
    }
    //Get protocol
    if (!canonicalURL)
    {
      curProtocol = window.location.protocol.split(':')[0];
    }
    else
    {
      curProtocol = canonicalURL.split(':')[0];
    }
    //Get current URL if the canonical URL does not exist
    if (!canonicalURL) canonicalURL = window.location.href;
    //Assign script content. Replace current URL with the canonical URL
    ! function ()
    {
      var e = /([http|https]:\/\/[a-zA-Z0-9\_\.]+\.baidu\.com)/gi,
        r = canonicalURL,
        t = document.referrer;
      if (!e.test(r))
      {
        var n = (String(curProtocol).toLowerCase() === 'https') ? "https://sp0.baidu.com/9_Q4simg2RQJ8t7jm9iCKT-xh_/s.gif" : "//api.share.baidu.com/s.gif";
        t ? (n += "?r=" + encodeURIComponent(document.referrer), r && (n += "&l=" + r)) : r && (n += "?l=" + r);
        var i = new Image;
        i.src = n
      }
    }(window);
  })();

</script>
<script src="/js/local-search.js"></script>
<script src="/.js"></script>

  

  

  



</body>
</html>
